diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000000..0b8534b7c9 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,7 @@ +reviews: + auto_review: + base_branches: + - main + - 1.6.x + - 1.7.x + - feat-sites # temporary until merged to 1.7.x \ No newline at end of file diff --git a/.env b/.env index 8ff8164a21..07f6cf8661 100644 --- a/.env +++ b/.env @@ -18,11 +18,15 @@ _APP_SYSTEM_RESPONSE_FORMAT= _APP_OPTIONS_ABUSE=disabled _APP_OPTIONS_ROUTER_PROTECTION=disabled _APP_OPTIONS_FORCE_HTTPS=disabled -_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled +_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled _APP_OPENSSL_KEY_V1=your-secret-key _APP_DOMAIN=traefik _APP_DOMAIN_FUNCTIONS=functions.localhost -_APP_DOMAIN_TARGET=localhost +_APP_DOMAIN_SITES=sites.localhost +_APP_DOMAIN_TARGET_CNAME=test.appwrite.io +_APP_DOMAIN_TARGET_A=127.0.0.1 +_APP_DOMAIN_TARGET_AAAA=::1 +_APP_RULES_FORMAT=md5 _APP_REDIS_HOST=redis _APP_REDIS_PORT=6379 _APP_REDIS_PASS= @@ -38,6 +42,7 @@ _APP_STORAGE_S3_ACCESS_KEY= _APP_STORAGE_S3_SECRET= _APP_STORAGE_S3_REGION=us-east-1 _APP_STORAGE_S3_BUCKET= +_APP_STORAGE_S3_ENDPOINT= _APP_STORAGE_DO_SPACES_ACCESS_KEY= _APP_STORAGE_DO_SPACES_SECRET= _APP_STORAGE_DO_SPACES_REGION=us-east-1 @@ -67,24 +72,28 @@ _APP_SMS_FROM=+123456789 _APP_SMS_PROJECTS_DENY_LIST= _APP_STORAGE_LIMIT=30000000 _APP_STORAGE_PREVIEW_LIMIT=20000000 -_APP_FUNCTIONS_SIZE_LIMIT=30000000 +_APP_COMPUTE_SIZE_LIMIT=30000000 _APP_FUNCTIONS_TIMEOUT=900 -_APP_FUNCTIONS_BUILD_TIMEOUT=900 -_APP_FUNCTIONS_CPUS=8 -_APP_FUNCTIONS_MEMORY=8192 -_APP_FUNCTIONS_INACTIVE_THRESHOLD=600 -_APP_FUNCTIONS_MAINTENANCE_INTERVAL=600 -_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes +_APP_SITES_TIMEOUT=30 +_APP_COMPUTE_BUILD_TIMEOUT=900 +_APP_COMPUTE_CPUS=8 +_APP_COMPUTE_MEMORY=8192 +_APP_COMPUTE_INACTIVE_THRESHOLD=600 +_APP_COMPUTE_MAINTENANCE_INTERVAL=600 +_APP_COMPUTE_RUNTIMES_NETWORK=runtimes _APP_EXECUTOR_SECRET=your-secret-key -_APP_EXECUTOR_HOST=http://proxy/v1 +_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_MAINTENANCE_INTERVAL=86400 _APP_MAINTENANCE_DELAY= _APP_MAINTENANCE_RETENTION_CACHE=2592000 _APP_MAINTENANCE_RETENTION_EXECUTION=1209600 _APP_MAINTENANCE_RETENTION_ABUSE=86400 _APP_MAINTENANCE_RETENTION_AUDIT=1209600 +_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800 _APP_USAGE_AGGREGATION_INTERVAL=30 +_APP_STATS_RESOURCES_INTERVAL=30 _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000 _APP_MAINTENANCE_RETENTION_SCHEDULES=86400 _APP_USAGE_STATS=enabled @@ -108,3 +117,5 @@ _APP_MESSAGE_EMAIL_TEST_DSN= _APP_MESSAGE_PUSH_TEST_DSN= _APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10 _APP_PROJECT_REGIONS=default +_APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000 +_APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main \ No newline at end of file diff --git a/.github/workflows/cleanup-cache.yml b/.github/workflows/cleanup-cache.yml index 6e20b8f879..8f25fe5ef6 100644 --- a/.github/workflows/cleanup-cache.yml +++ b/.github/workflows/cleanup-cache.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cleanup run: | diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 050f80b10a..a40f07ceda 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,8 +13,13 @@ on: schedule: - cron: '0 16 * * 0' +permissions: + contents: read + jobs: analyze: + permissions: + security-events: write name: Analyze runs-on: ubuntu-latest @@ -29,7 +34,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 899c27a135..02edd57923 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 2 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f914e662d3..c78156ca04 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 2 submodules: recursive @@ -26,7 +26,7 @@ jobs: - name: Login to Docker Hub uses: docker/login-action@v2 with: - username: ${{ secrets.DOCKERHUB_USERNAME }} + username: ${{ vars.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4475a49809..862d669466 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -28,7 +28,7 @@ jobs: - name: Login to Docker Hub uses: docker/login-action@v2 with: - username: ${{ secrets.DOCKERHUB_USERNAME }} + username: ${{ vars.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker diff --git a/.github/workflows/sdk-preview.yml b/.github/workflows/sdk-preview.yml new file mode 100644 index 0000000000..92b4f454cb --- /dev/null +++ b/.github/workflows/sdk-preview.yml @@ -0,0 +1,33 @@ +name: "Console SDK Preview" + +on: + pull_request: + paths: + - 'app/config/specs/*-latest-console.json' + + +jobs: + setup: + name: Setup & Build Console SDK + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Load and Start Appwrite + run: | + docker compose build + docker compose up -d + docker compose exec appwrite sdks --platform=console --sdk=web --version=latest --git=no + sudo chown -R $USER:$USER ./app/sdks/console-web + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Build and Publish SDK + working-directory: ./app/sdks/console-web + run: | + npm install + npm run build + npx pkg-pr-new publish --comment=update diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml new file mode 100644 index 0000000000..04f8c822c7 --- /dev/null +++ b/.github/workflows/static-analysis.yml @@ -0,0 +1,16 @@ +name: "Static code analysis" + +on: [pull_request] +jobs: + lint: + name: CodeQL + runs-on: ubuntu-latest + + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Run CodeQL + run: | + docker run --rm -v $PWD:/app composer:2.6 sh -c \ + "composer install --profile --ignore-platform-reqs && composer check" \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 29aa9b0581..645d5cb560 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,9 +8,33 @@ env: IMAGE: appwrite-dev CACHE_KEY: appwrite-dev-${{ github.event.pull_request.head.sha }} -on: [pull_request] +on: [ pull_request ] jobs: + check_database_changes: + name: Check if utopia-php/database changed + runs-on: ubuntu-latest + outputs: + database_changed: ${{ steps.check.outputs.database_changed }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Fetch base branch + run: git fetch origin ${{ github.event.pull_request.base.ref }} + + - name: Check for utopia-php/database changes + id: check + run: | + if git diff origin/${{ github.event.pull_request.base.ref }} HEAD -- composer.lock | grep -q '"name": "utopia-php/database"'; then + echo "Database version changed, going to run all mode tests." + echo "database_changed=true" >> "$GITHUB_ENV" + echo "database_changed=true" >> "$GITHUB_OUTPUT" + else + echo "database_changed=false" >> "$GITHUB_ENV" + echo "database_changed=false" >> "$GITHUB_OUTPUT" + fi + setup: name: Setup & Build Appwrite Image runs-on: ubuntu-latest @@ -66,6 +90,9 @@ jobs: docker compose up -d sleep 10 + - name: Logs + run: docker compose logs appwrite + - name: Doctor run: docker compose exec -T appwrite doctor @@ -95,6 +122,14 @@ jobs: docker load --input /tmp/${{ env.IMAGE }}.tar docker compose up -d sleep 10 + + - name: Wait for Open Runtimes + timeout-minutes: 3 + run: | + while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do + echo "Waiting for Executor to come online" + sleep 1 + done - name: Run General Tests run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/General --debug @@ -103,6 +138,72 @@ jobs: name: E2E Service Test runs-on: ubuntu-latest needs: setup + strategy: + fail-fast: false + matrix: + service: [ + Account, + Avatars, + Console, + Databases, + Functions, + FunctionsSchedule, + GraphQL, + Health, + Locale, + Projects, + Realtime, + Sites, + Proxy, + Storage, + Teams, + Users, + Webhooks, + VCS, + Messaging, + Migrations + ] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Load Cache + uses: actions/cache@v4 + with: + key: ${{ env.CACHE_KEY }} + path: /tmp/${{ env.IMAGE }}.tar + fail-on-cache-miss: true + + - name: Load and Start Appwrite + run: | + docker load --input /tmp/${{ env.IMAGE }}.tar + docker compose up -d + sleep 30 + + - name: Wait for Open Runtimes + timeout-minutes: 3 + run: | + while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do + echo "Waiting for Executor to come online" + sleep 1 + done + + - name: Run ${{ matrix.service }} tests with Project table mode + run: | + echo "Using project tables" + export _APP_DATABASE_SHARED_TABLES= + export _APP_DATABASE_SHARED_TABLES_V1= + + 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 + + e2e_shared_mode_test: + name: E2E Shared Mode Service Test + runs-on: ubuntu-latest + needs: [ setup, check_database_changes ] + if: needs.check_database_changes.outputs.database_changed == 'true' strategy: fail-fast: false matrix: @@ -119,6 +220,8 @@ jobs: Locale, Projects, Realtime, + Sites, + Proxy, Storage, Teams, Users, @@ -127,6 +230,10 @@ jobs: Messaging, Migrations ] + tables-mode: [ + 'Shared V1', + 'Shared V2', + ] steps: - name: checkout @@ -145,16 +252,37 @@ jobs: docker compose up -d sleep 30 - - name: Run ${{matrix.service}} Tests - run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug + - name: Wait for Open Runtimes + timeout-minutes: 3 + run: | + while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do + echo "Waiting for Executor to come online" + sleep 1 + done - - name: Run ${{matrix.service}} Shared Tables Tests - run: _APP_DATABASE_SHARED_TABLES=database_db_main docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug + - name: Run ${{ matrix.service }} tests with ${{ matrix.tables-mode }} table mode + run: | + if [ "${{ matrix.tables-mode }}" == "Shared V1" ]; then + echo "Using shared tables V1" + export _APP_DATABASE_SHARED_TABLES=database_db_main + export _APP_DATABASE_SHARED_TABLES_V1=database_db_main + elif [ "${{ matrix.tables-mode }}" == "Shared V2" ]; then + echo "Using shared tables V2" + export _APP_DATABASE_SHARED_TABLES=database_db_main + export _APP_DATABASE_SHARED_TABLES_V1= + fi + + 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 benchmarking: name: Benchmark runs-on: ubuntu-latest needs: setup + permissions: + pull-requests: write steps: - name: Checkout repository uses: actions/checkout@v4 @@ -215,6 +343,7 @@ jobs: path: benchmark.json retention-days: 7 - name: Find Comment + if: github.event.pull_request.head.repo.full_name == github.repository uses: peter-evans/find-comment@v3 id: fc with: @@ -222,6 +351,7 @@ jobs: comment-author: 'github-actions[bot]' body-includes: Benchmark results - name: Comment on PR + if: github.event.pull_request.head.repo.full_name == github.repository uses: peter-evans/create-or-update-comment@v4 with: comment-id: ${{ steps.fc.outputs.comment-id }} diff --git a/.gitignore b/.gitignore index 0d2b4b51ff..600a6aeb08 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /node_modules/ /tests/resources/storage/ /tests/resources/functions/**/code.tar.gz +/tests/resources/sites/**/code.tar.gz /app/sdks/* /.idea/ !/.idea/workspace.xml @@ -16,4 +17,4 @@ dev/yasd_init.php .phpunit.result.cache Makefile appwrite.json -.zed/ \ No newline at end of file +/.zed/ \ No newline at end of file diff --git a/.gitpod.yml b/.gitpod.yml index 478b62fc8d..78375bb1f0 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -7,6 +7,7 @@ tasks: docker pull composer command: | docker run --rm --interactive --tty \ + --user "$(id -u):$(id -g)" \ --volume $PWD:/app \ composer install \ --ignore-platform-reqs \ @@ -23,11 +24,3 @@ vscode: extensions: - ms-azuretools.vscode-docker - zobo.php-intellisense - -github: - # https://www.gitpod.io/docs/prebuilds#github-specific-configuration - prebuilds: - # enable for pull requests coming from forks (defaults to false) - pullRequestsFromForks: true - # add a check to pull requests (defaults to true) - addCheck: false diff --git a/CHANGES.md b/CHANGES.md index 9b6172eeab..62db3d525e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,117 @@ +# Version 1.6.1 + +## What's Changed + +### Notable changes + +* Remove JPEG fallback for webp by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8746 +* Add heic and avif support by @lohanidamodar in https://github.com/appwrite/appwrite/pull/7718 +* Add new runtimes by @Meldiron in https://github.com/appwrite/appwrite/pull/8771 +* Remove audits deletion by @shimonewman in https://github.com/appwrite/appwrite/pull/8766 +* Bump assistant by @loks0n in https://github.com/appwrite/appwrite/pull/8801 +* Change max queries values to 500 by @fogelito in https://github.com/appwrite/appwrite/pull/8802 +* Allow '.wav' as 'audio/x-wav' as well by @basert in https://github.com/appwrite/appwrite/pull/8846 +* Use 1 instead of 0.5 cpu for default function specification by @loks0n in https://github.com/appwrite/appwrite/pull/8848 +* Update function runtimes by @christyjacob4 in https://github.com/appwrite/appwrite/pull/8781 +* Add a realtime heartbeat by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/8943 + +### Fixes + +* Trigger functions event only if event is not paused by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8526 +* Update docker-compose to restart usage-dump by @feschaffa in https://github.com/appwrite/appwrite/pull/8642 +* Fix typo in scheduler base by @fogelito in https://github.com/appwrite/appwrite/pull/8691 +* Add domain and force HTTPS env vars to mail worker by @stnguyen90 in https://github.com/appwrite/appwrite/pull/8722 +* Fix webp by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8732 +* Ignore junction tables by @fogelito in https://github.com/appwrite/appwrite/pull/8728 +* Fix logger throwing fatal error by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8724 +* Fix missing protocol for testing SMTP by @byawitz in https://github.com/appwrite/appwrite/pull/8749 +* Make create execution async loose by @loks0n in https://github.com/appwrite/appwrite/pull/8707 +* Fix invalid cursor value by @fogelito in https://github.com/appwrite/appwrite/pull/8109 +* Fix target deletes by @abnegate in https://github.com/appwrite/appwrite/pull/8833 +* Fix translation commas by @loks0n in https://github.com/appwrite/appwrite/pull/8892 +* Fix Migrations having source creds being overwritten and add Migration tests by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8897 +* Fix validator usage for updating string size by @abnegate in https://github.com/appwrite/appwrite/pull/8890 +* Fix create user event not triggering by @loks0n in https://github.com/appwrite/appwrite/pull/8718 +* Improve error handling and logging in the database worker by @fogelito in https://github.com/appwrite/appwrite/pull/8944 +* Remove inaccurate info about leaving the URL parameter empty by @ebenezerdon in https://github.com/appwrite/appwrite/pull/8963 +* Ensure indexes are updated when updating an attribute key by @fogelito in https://github.com/appwrite/appwrite/pull/8971 +* Remove duplicate dart-2.16 runtime template by @stnguyen90 in https://github.com/appwrite/appwrite/pull/8972 +* Fix team invites with existing session by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/9006 +* Improve handling of HTTP requests by dispatching to safe workers by @Meldiron in https://github.com/appwrite/appwrite/pull/9016 +* Fix users create session secret by @stnguyen90 in https://github.com/appwrite/appwrite/pull/9019 +* Fix swoole task warning by @Meldiron in https://github.com/appwrite/appwrite/pull/9025 + +### Miscellaneous + +* Update Init copy by @adityaoberai in https://github.com/appwrite/appwrite/pull/8557 +* Fix security scan permissions and comment by @EVDOG4LIFE in https://github.com/appwrite/appwrite/pull/8525 +* Add Trivy security scans by @btme0011 in https://github.com/appwrite/appwrite/pull/6876 +* Update database stack by @abnegate in https://github.com/appwrite/appwrite/pull/8564 +* Bump database by @abnegate in https://github.com/appwrite/appwrite/pull/8573 +* Sync main with 1.5.x by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8589 +* Add AWS to one-click installs by @byawitz in https://github.com/appwrite/appwrite/pull/8593 +* Update Init copy in readme by @adityaoberai in https://github.com/appwrite/appwrite/pull/8618 +* Sync main into 1.6.x by @stnguyen90 in https://github.com/appwrite/appwrite/pull/8685 +* Sync 1.6.x into main by @stnguyen90 in https://github.com/appwrite/appwrite/pull/8686 +* Feat coroutines by @Meldiron in https://github.com/appwrite/appwrite/pull/7826 +* Sync main into 1.6.x by @Meldiron in https://github.com/appwrite/appwrite/pull/8719 +* Sentence casing endpoint API reference by @choir241 in https://github.com/appwrite/appwrite/pull/8617 +* DB storage metrics by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8404 +* Fix exception thrown when optional array attribute does not exist by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8391 +* Add projects channels to realtime by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/8735 +* Base for console roles support by @lohanidamodar in https://github.com/appwrite/appwrite/pull/8565 +* Remove DB disk storage calculation by @christyjacob4 in https://github.com/appwrite/appwrite/pull/8745 +* Messaging adapter default values by @shimonewman in https://github.com/appwrite/appwrite/pull/8742 +* Add payload response type by @loks0n in https://github.com/appwrite/appwrite/pull/8720 +* Fix flaky functions tests by @loks0n in https://github.com/appwrite/appwrite/pull/8682 +* Migrations Backups by @fogelito in https://github.com/appwrite/appwrite/pull/8186 +* Add test for response and request filters by @vermakhushboo in https://github.com/appwrite/appwrite/pull/8697 +* Bump version in SECURITY.md by @EVDOG4LIFE in https://github.com/appwrite/appwrite/pull/8755 +* Add originalId attribute to databases collection by @fogelito in https://github.com/appwrite/appwrite/pull/8764 +* Fix Walter References by @ItzNotABug in https://github.com/appwrite/appwrite/pull/8757 +* Update database by @abnegate in https://github.com/appwrite/appwrite/pull/8769 +* Move new attributes by @abnegate in https://github.com/appwrite/appwrite/pull/8777 +* Add ping endpoint by @loks0n in https://github.com/appwrite/appwrite/pull/8761 +* Fix GitHub action caching by @loks0n in https://github.com/appwrite/appwrite/pull/8772 +* Chore release ruby SDK by @abnegate in https://github.com/appwrite/appwrite/pull/8767 +* Call migration success on success by @abnegate in https://github.com/appwrite/appwrite/pull/8782 +* Update utopia-php/system to 0.9.0 by @basert in https://github.com/appwrite/appwrite/pull/8780 +* Move createDocument from api to worker by @vermakhushboo in https://github.com/appwrite/appwrite/pull/8776 +* Add missing indexes by @christyjacob4 in https://github.com/appwrite/appwrite/pull/8803 +* Update database by @abnegate in https://github.com/appwrite/appwrite/pull/8809 +* Fix typo in BLR region by @stnguyen90 in https://github.com/appwrite/appwrite/pull/8756 +* Add tests for project variables by @vermakhushboo in https://github.com/appwrite/appwrite/pull/8815 +* Replace 'Expires' with 'Cache-Control: private' header to avoid CDN caching by @basert in https://github.com/appwrite/appwrite/pull/8836 +* Allow blocking based on resource attributes by @basert in https://github.com/appwrite/appwrite/pull/8812 +* Check if resource is blocked inside functions worker by @basert in https://github.com/appwrite/appwrite/pull/8855 +* Fix missing allow attribute by @abnegate in https://github.com/appwrite/appwrite/pull/8889 +* Revert function execution order by @basert in https://github.com/appwrite/appwrite/pull/8857 +* Use resource type constants by @basert in https://github.com/appwrite/appwrite/pull/8895 +* Update Database lib by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8680 +* Update database by @abnegate in https://github.com/appwrite/appwrite/pull/8917 +* Update database by @abnegate in https://github.com/appwrite/appwrite/pull/8923 +* Update database for transaction counter fixes with retries by @abnegate in https://github.com/appwrite/appwrite/pull/8927 +* Validate string permissions by @fogelito in https://github.com/appwrite/appwrite/pull/8929 +* Add PubSub adapter support by @basert in https://github.com/appwrite/appwrite/pull/8905 +* List memberships as client by @loks0n in https://github.com/appwrite/appwrite/pull/8913 +* Fix XDebug Extension not being removed by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8891 +* Update database by @abnegate in https://github.com/appwrite/appwrite/pull/8946 +* Use utopia compression by @loks0n in https://github.com/appwrite/appwrite/pull/8938 +* Make compression minimum size configurable by @loks0n in https://github.com/appwrite/appwrite/pull/8947 +* Revert "Update database" by @christyjacob4 in https://github.com/appwrite/appwrite/pull/8949 +* Fix setpaused by @loks0n in https://github.com/appwrite/appwrite/pull/8948 +* Use getDocument instead of find() for rules by @christyjacob4 in https://github.com/appwrite/appwrite/pull/8951 +* Remove double fetch from migrations worker by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8956 +* Fix memberships privacy MFA by @loks0n in https://github.com/appwrite/appwrite/pull/8969 +* Add telemetry by @basert in https://github.com/appwrite/appwrite/pull/8960 +* Send migration errors individually by @PineappleIOnic in https://github.com/appwrite/appwrite/pull/8959 +* Add console sdk previews by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/8990 +* Unset index length by @fogelito in https://github.com/appwrite/appwrite/pull/8978 +* Update base to 0.9.5 by @basert in https://github.com/appwrite/appwrite/pull/9005 +* Sync main into 1.6.x by @TorstenDittmann in https://github.com/appwrite/appwrite/pull/9011 +* Improved shared tables V2 by @abnegate in https://github.com/appwrite/appwrite/pull/9013 +* Ensure backwards compatibility for 1.6.x by @christyjacob4 in https://github.com/appwrite/appwrite/pull/9018 + # Version 1.6.0 ## What's Changed diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b92361e51a..7746ef99af 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing -We would ❤️ you to contribute to Appwrite and help make it better! We want contributing to Appwrite to be fun, enjoyable, and educational for anyone and everyone. All contributions are welcome, including issues, and new docs, as well as updates and tweaks, blog posts, workshops, and more. +We would :heart: you to contribute to Appwrite and help make it better! We want contributing to Appwrite to be fun, enjoyable, and educational for anyone and everyone. All contributions are welcome, including issues, and new docs, as well as updates and tweaks, blog posts, workshops, and more. ## Here for Hacktoberfest? If you're here to contribute during Hacktoberfest, we're so happy to see you here. Appwrite has been a long-time participant of Hacktoberfest and we welcome you, whatever your experience level. This year, we're **only taking contributions for issues tagged** `hacktoberfest`, so we can focus our resources to support your contributions. @@ -9,13 +9,13 @@ You can [find issues using this query](https://github.com/search?q=org%3Aappwrit ## How to Start? -If you are worried or don’t know where to start, check out the next section that explains what kind of help we could use and where you can get involved. You can send your questions to [@appwrite](https://twitter.com/appwrite) on Twitter or to anyone from the [Appwrite team on Discord](https://appwrite.io/discord). You can also submit an issue, and a maintainer can guide you! +If you are worried or don’t know where to start, check out the next section that explains what kind of help we could use and where you can get involved. You can send your questions to [@appwrite on Twitter](https://twitter.com/appwrite) or to anyone from the [Appwrite team on Discord](https://appwrite.io/discord). You can also submit an issue, and a maintainer can guide you! ## Code of Conduct Help us keep Appwrite open and inclusive. Please read and follow our [Code of Conduct](https://github.com/appwrite/.github/blob/main/CODE_OF_CONDUCT.md). -## Submit a Pull Request 🚀 +## Submit a Pull Request :rocket: Branch naming convention is as following @@ -65,13 +65,13 @@ Now, go a step further by running the linter using the following command to manu composer lint ``` -This will give you a list of errors to rectify. If you need more information on the errors, you can pass in additional command line arguments to get more verbose information. More lists of available arguments can be found [here](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). A very useful command line argument is `--report=diff`. This will give you the expected changes by the linter for easy fixing of formatting issues. +This will give you a list of errors to rectify. If you need more information on the errors, you can pass in additional command line arguments to get more verbose information. More lists of available arguments can be found [on PHP_Codesniffer usage Wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). A very useful command line argument is `--report=diff`. This will give you the expected changes by the linter for easy fixing of formatting issues. ```bash composer lint --report=diff ``` -5. Push changes to GitHub. +5. Push changes to GitHub ``` $ git push origin [name_of_your_new_branch] @@ -163,6 +163,28 @@ Other containes should be named the same as their service, for example `redis` s - [Encryption](https://medium.com/searchencrypt/what-is-encryption-how-does-it-work-e8f20e340537#:~:text=Encryption%20is%20a%20process%20that,%2C%20or%20decrypt%2C%20the%20information.) - [Hashing](https://searchsqlserver.techtarget.com/definition/hashing#:~:text=Hashing%20is%20the%20transformation%20of,it%20using%20the%20original%20value.) +## Modules + +As Appwrite grows, we noticed approach of having all service endpoints in `app/controllers/api/[service].php` is not maintainable. Not only it creates massive files, it also doesnt contain all product's features such as workers or tasks. While there might still be some occurances of those controller files, we avoid it in all new development, and gradually migrate existing controllers to **HTTP modules**. + +### HTTP Endpoints + +Every endpoint file follows below structure, making it consistent with HTTP REST endpoint path: + +``` +src/Appwrite/Platform/Modules/[service]/Http/[resource]/[action].php +``` + +Tips and tricks: + +1. If endpoint doesn't have resource, use service name as resource name too +> Example: `Modules/Sites/Http/Sites/Get.php` + +2. If there are multiple resources, use then all in folder structure +> Example: `Modules/Sites/Http/Deployments/Builds/Create.php` + +3. Action can only be `Get`, `Create`, `Update`, `Delete` or `XList` + ## Architecture Appwrite's current structure is a combination of both [Monolithic](https://en.wikipedia.org/wiki/Monolithic_application) and [Microservice](https://en.wikipedia.org/wiki/Microservices) architectures. @@ -301,7 +323,7 @@ Adding a new dependency should have vital value for the product with minimum pos ## Introducing New Features -We would 💖 you to contribute to Appwrite, but we also want to ensure Appwrite is loyal to its vision and mission statement 🙏. +We would :sparkling_heart: you to contribute to Appwrite, but we also want to ensure Appwrite is loyal to its vision and mission statement :pray:. For us to find the right balance, please open an issue explaining your ideas before introducing a new pull request. @@ -367,7 +389,7 @@ In file `app/controllers/shared/api.php` On the database listener, add to an exi ```php case $document->getCollection() === 'teams': - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_TEAMS, $value); // per project break; ``` @@ -379,10 +401,10 @@ In that case you need also to handle children removal using addReduce() method c ```php case $document->getCollection() === 'buckets': //buckets - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_BUCKETS, $value); // per project if ($event === Database::EVENT_DOCUMENT_DELETE) { - $queueForUsage + $queueForStatsUsage ->addReduce($document); } break; @@ -428,16 +450,16 @@ public function __construct() ->inject('dbForProject') ->inject('queueForFunctions') ->inject('queueForEvents') - ->inject('queueForUsage') + ->inject('queueForStatsUsage') ->inject('log') - ->callback(fn (Message $message, Database $dbForProject, Func $queueForFunctions, Event $queueForEvents, Usage $queueForUsage, Log $log) => $this->action($message, $dbForProject, $queueForFunctions, $queueForEvents, $queueForUsage, $log)); + ->callback(fn (Message $message, Database $dbForProject, Func $queueForFunctions, Event $queueForEvents, StatsUsage $queueForStatsUsage, Log $log) => $this->action($message, $dbForProject, $queueForFunctions, $queueForEvents, $queueForStatsUsage, $log)); } ``` and then trigger the queue with the new metric like so: ```php -$queueForUsage +$queueForStatsUsage ->addMetric(METRIC_BUILDS, 1) ->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0)) ->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000) @@ -613,6 +635,18 @@ If you need to clear the cache, you can do so by running the following command: docker compose exec redis redis-cli FLUSHALL ``` +## Using preview domains locally + +Appwrite Functions are automatically given a domain you can visit to execute the function. This domain has format `[SOMETHING].functions.localhost` unless you changed `_APP_DOMAIN_FUNCTIONS` environment variable. This default value works great when running Appwrite locally, but it can be impossible to use preview domains with Cloud woekspaces such as Gitpod or GitHub Codespaces. + +To use preview domains on Cloud workspaces, you can visit hostname provided by them, and supply function's preview domain as URL parameter: + +``` +https://8080-appwrite-appwrite-mjeb3ebilwv.ws-eu116.gitpod.io/ping?preview=672b3c7eab1ac523ccf5.functions.localhost +``` + +The path was set to `/ping` intentionally. Visiting `/` for preview domains might trigger Console background worker, and trigger redirect to Console without our preview URL param. Visiting different path ensures this doesnt happen. + ## Tutorials From time to time, our team will add tutorials that will help contributors find their way in the Appwrite source code. Below is a list of currently available tutorials: @@ -628,7 +662,7 @@ Pull requests are great, but there are many other ways you can help Appwrite. ### Blogging & Speaking -Blogging, speaking about, or creating tutorials about one of Appwrite’s many features are great ways to get the word out about Appwrite. Mention [@appwrite](https://twitter.com/appwrite) on Twitter and/or [email team@appwrite.io](mailto:team@appwrite.io) so we can give pointers and tips and help you spread the word by promoting your content on the different Appwrite communication channels. Please add your blog posts and videos of talks to our [Awesome Appwrite](https://github.com/appwrite/awesome-appwrite) repo on GitHub. +Blogging, speaking about, or creating tutorials about one of Appwrite’s many features are great ways to get the word out about Appwrite. Mention [@appwrite on Twitter](https://twitter.com/appwrite) and/or [email team@appwrite.io](mailto:team@appwrite.io) so we can give pointers and tips and help you spread the word by promoting your content on the different Appwrite communication channels. Please add your blog posts and videos of talks to our [Awesome Appwrite](https://github.com/appwrite/awesome-appwrite) repo on GitHub. ### Presenting at Meetups diff --git a/Dockerfile b/Dockerfile index 07295f4afb..17f66b6074 100755 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ --no-plugins --no-scripts --prefer-dist \ `if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi` -FROM appwrite/base:0.9.3 AS final +FROM appwrite/base:0.10.1 AS final LABEL maintainer="team@appwrite.io" @@ -44,12 +44,14 @@ COPY ./dev /usr/src/code/dev # Set Volumes RUN mkdir -p /storage/uploads && \ + mkdir -p /storage/imports && \ mkdir -p /storage/cache && \ mkdir -p /storage/config && \ mkdir -p /storage/certificates && \ mkdir -p /storage/functions && \ mkdir -p /storage/debug && \ chown -Rf www-data.www-data /storage/uploads && chmod -Rf 0755 /storage/uploads && \ + chown -Rf www-data.www-data /storage/imports && chmod -Rf 0755 /storage/imports && \ chown -Rf www-data.www-data /storage/cache && chmod -Rf 0755 /storage/cache && \ chown -Rf www-data.www-data /storage/config && chmod -Rf 0755 /storage/config && \ chown -Rf www-data.www-data /storage/certificates && chmod -Rf 0755 /storage/certificates && \ @@ -68,6 +70,7 @@ RUN chmod +x /usr/local/bin/doctor && \ chmod +x /usr/local/bin/sdks && \ chmod +x /usr/local/bin/specs && \ chmod +x /usr/local/bin/ssl && \ + chmod +x /usr/local/bin/screenshot && \ chmod +x /usr/local/bin/test && \ chmod +x /usr/local/bin/upgrade && \ chmod +x /usr/local/bin/vars && \ @@ -85,8 +88,10 @@ RUN chmod +x /usr/local/bin/doctor && \ chmod +x /usr/local/bin/worker-messaging && \ chmod +x /usr/local/bin/worker-migrations && \ chmod +x /usr/local/bin/worker-webhooks && \ - chmod +x /usr/local/bin/worker-usage && \ - chmod +x /usr/local/bin/worker-usage-dump + chmod +x /usr/local/bin/worker-stats-usage && \ + chmod +x /usr/local/bin/worker-stats-usage-dump && \ + chmod +x /usr/local/bin/stats-resources && \ + chmod +x /usr/local/bin/worker-stats-resources # Letsencrypt Permissions RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/ diff --git a/README-CN.md b/README-CN.md index a5eac1be03..a81d99c3c3 100644 --- a/README-CN.md +++ b/README-CN.md @@ -1,8 +1,8 @@ -> 好消息!Appwrite 云现已进入公开测试版!立即访问 cloud.appwrite.io 注册,体验无忧的托管服务。今天就加入我们的云端吧!☁️🎉 +> 好消息!Appwrite 云现已进入公开测试版!立即访问 cloud.appwrite.io 注册,体验无忧的托管服务。今天就加入我们的云端吧!:cloud: :tada:

- Appwrite Logo + Appwrite banner with logo and slogan build like a team of hundreds

适用于[Flutter/Vue/Angular/React/iOS/Android/* 等等平台 *]的完整后端服务 @@ -36,6 +36,8 @@ Appwrite 可以提供给开发者用户验证,外部授权,用户数据读 内容: + +- [开始](#开始) - [安装](#安装) - [Unix](#unix) - [Windows](#windows) @@ -54,6 +56,9 @@ Appwrite 可以提供给开发者用户验证,外部授权,用户数据读 - [订阅我们](#订阅我们) - [版权说明](#版权说明) +## 开始 +要轻松开始使用Appwrite,您可以[**免费注册Appwrite Cloud**](https://cloud.appwrite.io/)。在Appwrite Cloud公开测试版期间,您可以完全免费使用Appwrite,而且我们不会收集您的信用卡信息。 + ## 安装 Appwrite 的容器化服务器只需要一行指令就可以运行。您可以使用 docker-compose 在本地主机上运行 Appwrite,也可以在任何其他容器化工具(如 [Kubernetes](https://kubernetes.io/docs/home/)、[Docker Swarm](https://docs.docker.com/engine/swarm/) 或 [Rancher](https://rancher.com/docs/))上运行 Appwrite。 @@ -67,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.6.0 + appwrite/appwrite:1.6.2 ``` ### Windows @@ -79,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.6.0 + appwrite/appwrite:1.6.2 ``` #### PowerShell @@ -89,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.6.0 + appwrite/appwrite:1.6.2 ``` 运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。 @@ -98,7 +103,42 @@ docker run -it --rm ` ### 从旧版本升级 -如果您从旧版本升级 Appwrite 服务器,则应在设置完成后使用 Appwrite 迁移工具。有关这方面的更多信息,请查看 [安装文档](https://appwrite.io/docs/installation)。 +如果您从旧版本升级 Appwrite 服务器,则应在设置完成后使用 Appwrite 迁移工具。有关这方面的更多信息,请查看 [安装文档](https://appwrite.io/docs/self-hosting)。 + +## 一键配置 + +除了在本地运行 Appwrite,您还可以使用预配置的设置启动 Appwrite。这样可以让您快速启动并运行 Appwrite,而无需在本地计算机上安装 Docker。 + +请从以下提供商中选择一个: + + + + + + + + +
+ + DigitalOcean Logo +
DigitalOcean
+ +
+ + Gitpod Logo +
Gitpod
+ +
+ + Akamai Logo +
Akamai Compute
+ +
+ + AWS Logo +
AWS Marketplace
+ +
## 入门 @@ -146,29 +186,25 @@ docker run -it --rm ` 以下是当前支持的平台和语言列表。如果您想帮助我们为您选择的平台添加支持,您可以访问我们的 [SDK 生成器](https://github.com/appwrite/sdk-generator) 项目并查看我们的 [贡献指南](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md)。 #### 客户端 - -- ✅   [Web](https://github.com/appwrite/sdk-for-web) (由 Appwrite 团队维护) -- ✅   [Flutter](https://github.com/appwrite/sdk-for-flutter) (由 Appwrite 团队维护) -- ✅   [Apple](https://github.com/appwrite/sdk-for-apple) (由 Appwrite 团队维护) -- ✅   [Android](https://github.com/appwrite/sdk-for-android) (由 Appwrite 团队维护) -- ✅   [React Native](https://github.com/appwrite/sdk-for-react-native) - **公测** (由 Appwrite 团队维护) +* :white_check_mark:   [Web](https://github.com/appwrite/sdk-for-web) (由 Appwrite 团队维护) +* :white_check_mark:   [Flutter](https://github.com/appwrite/sdk-for-flutter) (由 Appwrite 团队维护) +* :white_check_mark:   [Apple](https://github.com/appwrite/sdk-for-apple) - **公测** (由 Appwrite 团队维护) +* :white_check_mark:   [Android](https://github.com/appwrite/sdk-for-android) (由 Appwrite 团队维护) #### 服务器 - -- ✅   [NodeJS](https://github.com/appwrite/sdk-for-node) (由 Appwrite 团队维护) -- ✅   [PHP](https://github.com/appwrite/sdk-for-php) (由 Appwrite 团队维护) -- ✅   [Dart](https://github.com/appwrite/sdk-for-dart) (由 Appwrite 团队维护) -- ✅   [Deno](https://github.com/appwrite/sdk-for-deno) (由 Appwrite 团队维护) -- ✅   [Ruby](https://github.com/appwrite/sdk-for-ruby) (由 Appwrite 团队维护) -- ✅   [Python](https://github.com/appwrite/sdk-for-python) (由 Appwrite 团队维护) -- ✅   [Kotlin](https://github.com/appwrite/sdk-for-kotlin) (由 Appwrite 团队维护) -- ✅   [Swift](https://github.com/appwrite/sdk-for-swift) (由 Appwrite 团队维护) -- ✅   [.NET](https://github.com/appwrite/sdk-for-dotnet) - **公测** (由 Appwrite 团队维护) +* :white_check_mark:   [NodeJS](https://github.com/appwrite/sdk-for-node) (由 Appwrite 团队维护) +* :white_check_mark:   [PHP](https://github.com/appwrite/sdk-for-php) (由 Appwrite 团队维护) +* :white_check_mark:   [Dart](https://github.com/appwrite/sdk-for-dart) - (由 Appwrite 团队维护) +* :white_check_mark:   [Deno](https://github.com/appwrite/sdk-for-deno) - **公测** (由 Appwrite 团队维护) +* :white_check_mark:   [Ruby](https://github.com/appwrite/sdk-for-ruby) (由 Appwrite 团队维护) +* :white_check_mark:   [Python](https://github.com/appwrite/sdk-for-python) (由 Appwrite 团队维护) +* :white_check_mark:   [Kotlin](https://github.com/appwrite/sdk-for-kotlin) - **公测** (由 Appwrite 团队维护) +* :white_check_mark:   [Apple](https://github.com/appwrite/sdk-for-apple) - **公测** (由 Appwrite 团队维护) +* :white_check_mark:   [.NET](https://github.com/appwrite/sdk-for-dotnet) - **公测** (由 Appwrite 团队维护) #### 开发者社区 - -- ✅   [Appcelerator Titanium](https://github.com/m1ga/ti.appwrite) (维护者 [Michael Gangolf](https://github.com/m1ga/)) -- ✅   [Godot Engine](https://github.com/GodotNuts/appwrite-sdk) (维护者 [fenix-hub @GodotNuts](https://github.com/fenix-hub)) +* :white_check_mark:   [Appcelerator Titanium](https://github.com/m1ga/ti.appwrite) (维护者 [Michael Gangolf](https://github.com/m1ga/)) +* :white_check_mark:   [Godot Engine](https://github.com/GodotNuts/appwrite-sdk) (维护者 [fenix-hub @GodotNuts](https://github.com/fenix-hub)) 找不到需要的的 SDK? - 欢迎通过发起 PR 来帮助我们完善 Appwrite 的软件生态环境 [SDK 生成器](https://github.com/appwrite/sdk-generator)! diff --git a/README.md b/README.md index a9856a7310..c3585dbb68 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -> Appwrite Init has concluded! You can check out all the latest announcements [on our Init website](https://appwrite.io/init) 🚀 +> [Get started with Appwrite](https://apwr.dev/appcloud)

- Appwrite Logo + Appwrite banner, with logo and text saying

Appwrite is a backend platform for developing Web, Mobile, and Flutter applications. Built with the open source community and optimized for developer experience in the coding languages you love. @@ -12,11 +12,11 @@ -[![We're Hiring](https://img.shields.io/static/v1?label=We're&message=Hiring&color=blue&style=flat-square)](https://appwrite.io/company/careers) -[![Hacktoberfest](https://img.shields.io/static/v1?label=hacktoberfest&message=ready&color=191120&style=flat-square)](https://hacktoberfest.appwrite.io) -[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord?r=Github) -[![Build Status](https://img.shields.io/github/actions/workflow/status/appwrite/appwrite/tests.yml?branch=master&label=tests&style=flat-square)](https://github.com/appwrite/appwrite/actions) -[![X Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite) +[![We're Hiring label](https://img.shields.io/static/v1?label=We're&message=Hiring&color=blue&style=flat-square)](https://appwrite.io/company/careers) +[![Hacktoberfest label](https://img.shields.io/static/v1?label=hacktoberfest&message=ready&color=191120&style=flat-square)](https://hacktoberfest.appwrite.io) +[![Discord label](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord?r=Github) +[![Build Status label](https://img.shields.io/github/actions/workflow/status/appwrite/appwrite/tests.yml?branch=master&label=tests&style=flat-square)](https://github.com/appwrite/appwrite/actions) +[![X Account label](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite) @@ -24,11 +24,9 @@ English | [简体中文](README-CN.md) -[**Announcing Appwrite Cloud Public Beta! Sign up today!**](https://cloud.appwrite.io) - Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps packaged as a set of Docker microservices. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster. -Using Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, and [more services](https://appwrite.io/docs). +Using Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, messaging, and [more services](https://appwrite.io/docs).


@@ -37,13 +35,14 @@ Using Appwrite, you can easily integrate your app with user authentication and m

-![Appwrite](public/images/github.png) +![Appwrite project dashboard showing various Appwrite features](public/images/github.png) -Find out more at: [https://appwrite.io](https://appwrite.io) +Find out more at: [https://appwrite.io](https://appwrite.io). Table of Contents: -- [Installation](#installation) +- [Getting Started](#getting-started) +- [Self-Hosting](#self-hosting) - [Unix](#unix) - [Windows](#windows) - [CMD](#cmd) @@ -51,7 +50,7 @@ Table of Contents: - [Upgrade from an Older Version](#upgrade-from-an-older-version) - [One-Click Setups](#one-click-setups) - [Getting Started](#getting-started) - - [Services](#services) + - [Products](#products) - [SDKs](#sdks) - [Client](#client) - [Server](#server) @@ -62,11 +61,14 @@ Table of Contents: - [Follow Us](#follow-us) - [License](#license) -## Installation +## Getting Started +The easiest way to get started with Appwrite is by [signing up for Appwrite Cloud](https://cloud.appwrite.io/). While Appwrite Cloud is in public beta, you can build with Appwrite completely free, and we won't collect you credit card information. + +## Self-Hosting Appwrite is designed to run in a containerized environment. Running your server is as easy as running one command from your terminal. You can either run Appwrite on your localhost using docker-compose or on any other container orchestration tool, such as [Kubernetes](https://kubernetes.io/docs/home/), [Docker Swarm](https://docs.docker.com/engine/swarm/), or [Rancher](https://rancher.com/docs/). -The easiest way to start running your Appwrite server is by running our docker-compose file. Before running the installation command, make sure you have [Docker](https://www.docker.com/products/docker-desktop) installed on your machine: +Before running the installation command, make sure you have [Docker](https://www.docker.com/products/docker-desktop) installed on your machine: ### Unix @@ -75,7 +77,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.6.0 + appwrite/appwrite:1.6.2 ``` ### Windows @@ -87,7 +89,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.6.0 + appwrite/appwrite:1.6.2 ``` #### PowerShell @@ -97,7 +99,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.6.0 + appwrite/appwrite:1.6.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. @@ -106,7 +108,7 @@ For advanced production and custom installation, check out our Docker [environme ### Upgrade from an Older Version -If you are upgrading your Appwrite server from an older version, you should use the Appwrite migration tool once your setup is completed. For more information regarding this, check out the [Installation Docs](https://appwrite.io/docs/installation). +If you are upgrading your Appwrite server from an older version, you should use the Appwrite migration tool once your setup is completed. For more information regarding this, check out the [Installation Docs](https://appwrite.io/docs/self-hosting). ## One-Click Setups @@ -192,34 +194,34 @@ Below is a list of currently supported platforms and languages. If you would lik #### Client -- ✅   [Web](https://github.com/appwrite/sdk-for-web) (Maintained by the Appwrite Team) -- ✅   [Flutter](https://github.com/appwrite/sdk-for-flutter) (Maintained by the Appwrite Team) -- ✅   [Apple](https://github.com/appwrite/sdk-for-apple) (Maintained by the Appwrite Team) -- ✅   [Android](https://github.com/appwrite/sdk-for-android) (Maintained by the Appwrite Team) -- ✅   [React Native](https://github.com/appwrite/sdk-for-react-native) - **Beta** (Maintained by the Appwrite Team) +- :white_check_mark:   [Web](https://github.com/appwrite/sdk-for-web) (Maintained by the Appwrite Team) +- :white_check_mark:   [Flutter](https://github.com/appwrite/sdk-for-flutter) (Maintained by the Appwrite Team) +- :white_check_mark:   [Apple](https://github.com/appwrite/sdk-for-apple) (Maintained by the Appwrite Team) +- :white_check_mark:   [Android](https://github.com/appwrite/sdk-for-android) (Maintained by the Appwrite Team) +- :white_check_mark:   [React Native](https://github.com/appwrite/sdk-for-react-native) - **Beta** (Maintained by the Appwrite Team) #### Server -- ✅   [NodeJS](https://github.com/appwrite/sdk-for-node) (Maintained by the Appwrite Team) -- ✅   [PHP](https://github.com/appwrite/sdk-for-php) (Maintained by the Appwrite Team) -- ✅   [Dart](https://github.com/appwrite/sdk-for-dart) (Maintained by the Appwrite Team) -- ✅   [Deno](https://github.com/appwrite/sdk-for-deno) (Maintained by the Appwrite Team) -- ✅   [Ruby](https://github.com/appwrite/sdk-for-ruby) (Maintained by the Appwrite Team) -- ✅   [Python](https://github.com/appwrite/sdk-for-python) (Maintained by the Appwrite Team) -- ✅   [Kotlin](https://github.com/appwrite/sdk-for-kotlin) (Maintained by the Appwrite Team) -- ✅   [Swift](https://github.com/appwrite/sdk-for-swift) (Maintained by the Appwrite Team) -- ✅   [.NET](https://github.com/appwrite/sdk-for-dotnet) - **Beta** (Maintained by the Appwrite Team) +- :white_check_mark:   [NodeJS](https://github.com/appwrite/sdk-for-node) (Maintained by the Appwrite Team) +- :white_check_mark:   [PHP](https://github.com/appwrite/sdk-for-php) (Maintained by the Appwrite Team) +- :white_check_mark:   [Dart](https://github.com/appwrite/sdk-for-dart) (Maintained by the Appwrite Team) +- :white_check_mark:   [Deno](https://github.com/appwrite/sdk-for-deno) (Maintained by the Appwrite Team) +- :white_check_mark:   [Ruby](https://github.com/appwrite/sdk-for-ruby) (Maintained by the Appwrite Team) +- :white_check_mark:   [Python](https://github.com/appwrite/sdk-for-python) (Maintained by the Appwrite Team) +- :white_check_mark:   [Kotlin](https://github.com/appwrite/sdk-for-kotlin) (Maintained by the Appwrite Team) +- :white_check_mark:   [Swift](https://github.com/appwrite/sdk-for-swift) (Maintained by the Appwrite Team) +- :white_check_mark:   [.NET](https://github.com/appwrite/sdk-for-dotnet) - **Beta** (Maintained by the Appwrite Team) #### Community -- ✅   [Appcelerator Titanium](https://github.com/m1ga/ti.appwrite) (Maintained by [Michael Gangolf](https://github.com/m1ga/)) -- ✅   [Godot Engine](https://github.com/GodotNuts/appwrite-sdk) (Maintained by [fenix-hub @GodotNuts](https://github.com/fenix-hub)) +- :white_check_mark:   [Appcelerator Titanium](https://github.com/m1ga/ti.appwrite) (Maintained by [Michael Gangolf](https://github.com/m1ga/)) +- :white_check_mark:   [Godot Engine](https://github.com/GodotNuts/appwrite-sdk) (Maintained by [fenix-hub @GodotNuts](https://github.com/fenix-hub)) Looking for more SDKs? - Help us by contributing a pull request to our [SDK Generator](https://github.com/appwrite/sdk-generator)! ## Architecture -![Appwrite Architecture](docs/specs/overview.drawio.svg) +![Appwrite Architecture showing how Appwrite is built and the services and tools it uses](docs/specs/overview.drawio.svg) Appwrite uses a microservices architecture that was designed for easy scaling and delegation of responsibilities. In addition, Appwrite supports multiple APIs, such as REST, WebSocket, and GraphQL to allow you to interact with your resources by leveraging your existing knowledge and protocols of choice. @@ -229,7 +231,7 @@ The Appwrite API layer was designed to be extremely fast by leveraging in-memory All code contributions, including those of people having commit access, must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code. -We truly ❤️ pull requests! If you wish to help, you can learn more about how you can contribute to this project in the [contribution guide](CONTRIBUTING.md). +We truly :heart: pull requests! If you wish to help, you can learn more about how you can contribute to this project in the [contribution guide](CONTRIBUTING.md). ## Security diff --git a/app/cli.php b/app/cli.php index 23502ec402..b0e976451b 100644 --- a/app/cli.php +++ b/app/cli.php @@ -5,8 +5,11 @@ require_once __DIR__ . '/init.php'; use Appwrite\Event\Certificate; use Appwrite\Event\Delete; use Appwrite\Event\Func; +use Appwrite\Event\StatsResources; +use Appwrite\Event\StatsUsage; use Appwrite\Platform\Appwrite; use Appwrite\Runtimes\Runtimes; +use Executor\Executor; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\CLI; @@ -19,12 +22,12 @@ use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Service; use Utopia\Pools\Group; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; use Utopia\Registry\Registry; use Utopia\System\System; -// overwriting runtimes to be architectur agnostic for CLI -Config::setParam('runtimes', (new Runtimes('v4'))->getAll(supported: false)); +// overwriting runtimes to be architecture agnostic for CLI +Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false)); // require controllers after overwriting runtimes require_once __DIR__ . '/controllers/general.php'; @@ -41,8 +44,7 @@ CLI::setResource('cache', function ($pools) { $adapters[] = $pools ->get($value) ->pop() - ->getResource() - ; + ->getResource(); } return new Cache(new Sharding($adapters)); @@ -52,7 +54,7 @@ CLI::setResource('pools', function (Registry $register) { return $register->get('pools'); }, ['register']); -CLI::setResource('dbForConsole', function ($pools, $cache) { +CLI::setResource('dbForPlatform', function ($pools, $cache) { $sleep = 3; $maxAttempts = 5; $attempts = 0; @@ -67,9 +69,9 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { ->pop() ->getResource(); - $dbForConsole = new Database($dbAdapter, $cache); + $dbForPlatform = new Database($dbAdapter, $cache); - $dbForConsole + $dbForPlatform ->setNamespace('_console') ->setMetadata('host', \gethostname()) ->setMetadata('project', 'console'); @@ -78,7 +80,7 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { $collections = Config::getParam('collections', [])['console']; $last = \array_key_last($collections); - if (!($dbForConsole->exists($dbForConsole->getDatabase(), $last))) { /** TODO cache ready variable using registry */ + if (!($dbForPlatform->exists($dbForPlatform->getDatabase(), $last))) { /** TODO cache ready variable using registry */ throw new Exception('Tables not ready yet.'); } @@ -94,15 +96,19 @@ CLI::setResource('dbForConsole', function ($pools, $cache) { throw new Exception("Console is not ready yet. Please try again later."); } - return $dbForConsole; + return $dbForPlatform; }, ['pools', 'cache']); -CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) { +CLI::setResource('console', function () { + return new Document(Config::getParam('console')); +}, []); + +CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases) { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; + return $dbForPlatform; } try { @@ -114,8 +120,9 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, if (isset($databases[$dsn->getHost()])) { $database = $databases[$dsn->getHost()]; + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) @@ -136,10 +143,10 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, ->getResource(); $database = new Database($dbAdapter, $cache); - $databases[$dsn->getHost()] = $database; + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) @@ -157,20 +164,59 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $database; }; -}, ['pools', 'dbForConsole', 'cache']); +}, ['pools', 'dbForPlatform', 'cache']); -CLI::setResource('queue', function (Group $pools) { - return $pools->get('queue')->pop()->getResource(); +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 + ); + + $database + ->setSharedTables(true) + ->setNamespace('logsV1') + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_TASK) + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); + + // set tenant + if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { + $database->setTenant($project->getInternalId()); + } + + return $database; + }; +}, ['pools', 'cache']); + +CLI::setResource('queueForStatsUsage', function (Connection $publisher) { + return new StatsUsage($publisher); +}, ['publisher']); +CLI::setResource('queueForStatsResources', function (Publisher $publisher) { + return new StatsResources($publisher); +}, ['publisher']); +CLI::setResource('publisher', function (Group $pools) { + return $pools->get('publisher')->pop()->getResource(); }, ['pools']); -CLI::setResource('queueForFunctions', function (Connection $queue) { - return new Func($queue); -}, ['queue']); -CLI::setResource('queueForDeletes', function (Connection $queue) { - return new Delete($queue); -}, ['queue']); -CLI::setResource('queueForCertificates', function (Connection $queue) { - return new Certificate($queue); -}, ['queue']); +CLI::setResource('queueForFunctions', function (Publisher $publisher) { + return new Func($publisher); +}, ['publisher']); +CLI::setResource('queueForDeletes', function (Publisher $publisher) { + return new Delete($publisher); +}, ['publisher']); +CLI::setResource('queueForCertificates', function (Publisher $publisher) { + return new Certificate($publisher); +}, ['publisher']); CLI::setResource('logError', function (Registry $register) { return function (Throwable $error, string $namespace, string $action) use ($register) { $logger = $register->get('logger'); @@ -180,7 +226,7 @@ CLI::setResource('logError', function (Registry $register) { $log = new Log(); $log->setNamespace($namespace); - $log->setServer(\gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); @@ -210,6 +256,8 @@ CLI::setResource('logError', function (Registry $register) { }; }, ['register']); +CLI::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST'))); + $platform = new Appwrite(); $platform->init(Service::TYPE_TASK); diff --git a/app/config/avatars/credit-cards.php b/app/config/avatars/credit-cards.php index eb76c576cf..52760bf9dc 100644 --- a/app/config/avatars/credit-cards.php +++ b/app/config/avatars/credit-cards.php @@ -16,5 +16,6 @@ return [ 'union-china-pay' => ['name' => 'Union China Pay', 'path' => __DIR__ . '/credit-cards/union-china-pay.png'], 'visa' => ['name' => 'Visa', 'path' => __DIR__ . '/credit-cards/visa.png'], 'mir' => ['name' => 'MIR', 'path' => __DIR__ . '/credit-cards/mir.png'], - 'maestro' => ['name' => 'Maestro', 'path' => __DIR__ . '/credit-cards/maestro.png'] + 'maestro' => ['name' => 'Maestro', 'path' => __DIR__ . '/credit-cards/maestro.png'], + 'rupay' => ['name' => 'Rupay', 'path' => __DIR__ . '/credit-cards/rupay.png'] ]; diff --git a/app/config/avatars/credit-cards/rupay.png b/app/config/avatars/credit-cards/rupay.png new file mode 100644 index 0000000000..dfb95e9844 Binary files /dev/null and b/app/config/avatars/credit-cards/rupay.png differ diff --git a/app/config/collections.php b/app/config/collections.php index cc8fc2d420..533dee57a8 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1,12 +1,18 @@ $common['files']]; + +// no more required. +unset($common['files']); /** * $collection => id of the parent collection where this will be inserted @@ -17,6159 +23,12 @@ $auth = Config::getParam('auth', []); * indexes => list of indexes */ -$commonCollections = [ - 'cache' => [ - '$collection' => Database::METADATA, - '$id' => 'cache', - 'name' => 'Cache', - 'attributes' => [ - [ - '$id' => 'resource', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'resourceType', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mimeType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'accessedAt', - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => 'signature', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => '_key_accessedAt', - 'type' => Database::INDEX_KEY, - 'attributes' => ['accessedAt'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => '_key_resource', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resource'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'users' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('users'), - 'name' => 'Users', - 'attributes' => [ - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('email'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 320, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('phone'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16, // leading '+' and 15 digitts maximum by E.164 format - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('labels'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('passwordHistory'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('password'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => 'hash', // Hashing algorithm used to hash the password - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => Auth::DEFAULT_ALGO, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('hashOptions'), // Configuration of hashing algorithm - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => Auth::DEFAULT_ALGO_OPTIONS, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('passwordUpdate'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('prefs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => new \stdClass(), - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('registration'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('emailVerification'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('phoneVerification'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('reset'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mfa'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mfaRecoveryCodes'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('authenticators'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryAuthenticators'], - ], - [ - '$id' => ID::custom('sessions'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQuerySessions'], - ], - [ - '$id' => ID::custom('tokens'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryTokens'], - ], - [ - '$id' => ID::custom('challenges'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryChallenges'], - ], - [ - '$id' => ID::custom('memberships'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryMemberships'], - ], - [ - '$id' => ID::custom('targets'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryTargets'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['userSearch'], - ], - [ - '$id' => ID::custom('accessedAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_email'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['email'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_phone'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['phone'], - 'lengths' => [16], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_status'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['status'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_passwordUpdate'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['passwordUpdate'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_registration'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['registration'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_emailVerification'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['emailVerification'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_phoneVerification'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['phoneVerification'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => '_key_accessedAt', - 'type' => Database::INDEX_KEY, - 'attributes' => ['accessedAt'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'tokens' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('tokens'), - 'name' => 'Tokens', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('secret'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('expire'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('userAgent'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('ip'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 45, // https://stackoverflow.com/a/166157/2299554 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_user'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'authenticators' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('authenticators'), - 'name' => 'Authenticators', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('verified'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => false, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('data'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_userInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'challenges' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('challenges'), - 'name' => 'Challenges', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('token'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], [ - '$id' => ID::custom('code'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 512, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], [ - '$id' => ID::custom('expire'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_user'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'sessions' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('sessions'), - 'name' => 'Sessions', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('provider'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerUid'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerAccessToken'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('providerAccessTokenExpiry'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('providerRefreshToken'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('secret'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('userAgent'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('ip'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 45, // https://stackoverflow.com/a/166157/2299554 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('countryCode'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('osCode'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('osName'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('osVersion'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientCode'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientName'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientVersion'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientEngine'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('clientEngineVersion'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deviceName'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deviceBrand'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deviceModel'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('factors'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('expire'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('mfaUpdatedAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_provider_providerUid'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['provider', 'providerUid'], - 'lengths' => [128, 128], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_user'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'identities' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('identities'), - 'name' => 'Identities', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('provider'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerUid'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerEmail'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 320, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerAccessToken'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('providerAccessTokenExpiry'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('providerRefreshToken'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - // Used to store data from provider that may or may not be sensitive - '$id' => ID::custom('secrets'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_userInternalId_provider_providerUid'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['userInternalId', 'provider', 'providerUid'], - 'lengths' => [11, 128, 128], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_provider_providerUid'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['provider', 'providerUid'], - 'lengths' => [128, 128], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_userId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_userInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_provider'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['provider'], - 'lengths' => [128], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerUid'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerUid'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerEmail'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerEmail'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerAccessTokenExpiry'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerAccessTokenExpiry'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'teams' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('teams'), - 'name' => 'Teams', - 'attributes' => [ - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('total'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('prefs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => new \stdClass(), - 'array' => false, - 'filters' => ['json'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [128], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_total'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['total'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'memberships' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('memberships'), - 'name' => 'Memberships', - 'attributes' => [ - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('teamInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('teamId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('roles'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('invited'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('joined'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('confirm'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('secret'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_unique'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['teamInternalId', 'userInternalId'], - 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_user'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_team'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['teamInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_userId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_teamId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['teamId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_invited'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['invited'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_joined'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['joined'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_confirm'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['confirm'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'buckets' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('buckets'), - 'name' => 'Buckets', - 'attributes' => [ - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => 128, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('fileSecurity'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 1, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('maximumFileSize'), - 'type' => Database::VAR_INTEGER, - 'signed' => false, - 'size' => 8, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('allowedFileExtensions'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => 64, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => true, - ], - [ - '$id' => 'compression', - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => 10, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('encryption'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('antivirus'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_fulltext_name'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_enabled'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['enabled'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_fileSecurity'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['fileSecurity'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_maximumFileSize'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['maximumFileSize'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_encryption'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['encryption'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_antivirus'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['antivirus'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ] - ], - - 'stats' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('stats'), - 'name' => 'Stats', - 'attributes' => [ - [ - '$id' => ID::custom('metric'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('region'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('value'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 8, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('time'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('period'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 4, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_time'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['time'], - 'lengths' => [], - 'orders' => [Database::ORDER_DESC], - ], - [ - '$id' => ID::custom('_key_period_time'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['period', 'time'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_metric_period_time'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['metric', 'period', 'time'], - 'lengths' => [], - 'orders' => [Database::ORDER_DESC], - ], - ], - ], - - 'providers' => [ - '$collection' => ID::custom(DATABASE::METADATA), - '$id' => ID::custom('providers'), - 'name' => 'Providers', - 'attributes' => [ - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('provider'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'default' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('credentials'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - [ - '$id' => ID::custom('options'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => ['providerSearch'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_provider'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['provider'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_type'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['type'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_enabled_type'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['enabled', 'type'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ] - ], - ], - - 'messages' => [ - '$collection' => ID::custom(DATABASE::METADATA), - '$id' => ID::custom('messages'), - 'name' => 'Messages', - 'attributes' => [ - [ - '$id' => ID::custom('providerType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => 'processing', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('data'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('topics'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 21845, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('users'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 21845, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('targets'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 21845, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduledAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('scheduleInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduleId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deliveredAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('deliveryErrors'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('deliveredTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => ['messageSearch'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'topics' => [ - '$collection' => ID::custom(DATABASE::METADATA), - '$id' => ID::custom('topics'), - 'name' => 'Topics', - 'attributes' => [ - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('subscribe'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('emailTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('smsTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('pushTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('targets'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryTopicTargets'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => ['topicSearch'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['name'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'subscribers' => [ - '$collection' => ID::custom(DATABASE::METADATA), - '$id' => ID::custom('subscribers'), - 'name' => 'Subscribers', - 'attributes' => [ - [ - '$id' => ID::custom('targetId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('targetInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('topicId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('topicInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_targetId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['targetId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_targetInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['targetInternalId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_userId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_userInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_topicId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['topicId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_topicInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['topicInternalId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_unique_target_topic'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['targetInternalId', 'topicInternalId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'targets' => [ - '$collection' => ID::custom(DATABASE::METADATA), - '$id' => ID::custom('targets'), - 'name' => 'Targets', - 'attributes' => [ - [ - '$id' => ID::custom('userId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('userInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('sessionId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('sessionInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('identifier'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('expired'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => false, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_userId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userId'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_userInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['userInternalId'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_providerInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerInternalId'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_identifier'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['identifier'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], -]; - -$projectCollections = array_merge([ - 'databases' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('databases'), - 'name' => 'Databases', - 'attributes' => [ - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'size' => 256, - 'required' => true, - 'signed' => true, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('originalId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => null, - 'array' => false, - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'attributes' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('attributes'), - 'name' => 'Attributes', - 'attributes' => [ - [ - '$id' => ID::custom('databaseInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('databaseId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => false, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('collectionInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('collectionId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('key'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('error'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('size'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('required'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('default'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['casting'], - ], - [ - '$id' => ID::custom('signed'), - 'type' => Database::VAR_BOOLEAN, - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('array'), - 'type' => Database::VAR_BOOLEAN, - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('format'), - 'type' => Database::VAR_STRING, - 'size' => 64, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('formatOptions'), - 'type' => Database::VAR_STRING, - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => new stdClass(), - 'array' => false, - 'filters' => ['json', 'range', 'enum'], - ], - [ - '$id' => ID::custom('filters'), - 'type' => Database::VAR_STRING, - 'size' => 64, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('options'), - 'type' => Database::VAR_STRING, - 'size' => 16384, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_db_collection'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['databaseInternalId', 'collectionInternalId'], - 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - ], - ], - - 'indexes' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('indexes'), - 'name' => 'Indexes', - 'attributes' => [ - [ - '$id' => ID::custom('databaseInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('databaseId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => false, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('collectionInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('collectionId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('key'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('error'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('attributes'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('lengths'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('orders'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 4, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_db_collection'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['databaseInternalId', 'collectionInternalId'], - 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - ], - ], - - 'functions' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('functions'), - 'name' => 'Functions', - 'attributes' => [ - [ - '$id' => ID::custom('execute'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('live'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('installationId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('installationInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerRepositoryId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('repositoryId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('repositoryInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerBranch'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerRootDirectory'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerSilentMode'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('logging'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('runtime'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deployment'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('vars'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryVariables'], - ], - [ - '$id' => ID::custom('varsProject'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryProjectVariables'], - ], - [ - '$id' => ID::custom('events'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduleInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduleId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('schedule'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('timeout'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('version'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 8, - 'signed' => true, - 'required' => false, - 'default' => 'v4', - 'array' => false, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('entrypoint'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('commands'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('specification'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => false, - 'required' => false, - 'default' => APP_FUNCTION_SPECIFICATION_DEFAULT, - 'filters' => [], - ], - [ - '$id' => ID::custom('scopes'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_enabled'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['enabled'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_installationId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_installationInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerRepositoryId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerRepositoryId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_repositoryId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['repositoryId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_repositoryInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['repositoryInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_runtime'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['runtime'], - 'lengths' => [64], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_deployment'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['deployment'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'deployments' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('deployments'), - 'name' => 'Deployments', - 'attributes' => [ - [ - '$id' => ID::custom('resourceInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('buildInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('buildId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('entrypoint'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('commands'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - '$id' => ID::custom('path'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('installationId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('installationInternalId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerRepositoryId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('repositoryId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('repositoryInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerRepositoryName'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerRepositoryOwner'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerRepositoryUrl'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommitHash'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommitAuthorUrl'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommitAuthor'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommitMessage'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommitUrl'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerBranch'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerBranchUrl'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerRootDirectory'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('providerCommentId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => 2048, - 'format' => '', - 'filters' => [], - 'required' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('size'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('metadata'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('chunksTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('chunksUploaded'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('activate'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => false, - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_resource'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceId'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_resource_type'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceType'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_size'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['size'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_buildId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['buildId'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_activate'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['activate'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'builds' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('builds'), - 'name' => 'Builds', - 'attributes' => [ - [ - '$id' => ID::custom('startTime'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('endTime'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('duration'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('size'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('runtime'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => true, - 'default' => 'processing', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('path'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('logs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('sourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => 'local', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('source'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => true, - 'default' => '', - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_deployment'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['deploymentId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'executions' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('executions'), - 'name' => 'Executions', - 'attributes' => [ - [ - '$id' => ID::custom('functionInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('functionId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('deploymentId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('trigger'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('duration'), - 'type' => Database::VAR_FLOAT, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('errors'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('logs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('requestMethod'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('requestPath'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - '$id' => ID::custom('requestHeaders'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('responseStatusCode'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('responseHeaders'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduledAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('scheduleInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('scheduleId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_function'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['functionId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_trigger'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['trigger'], - 'lengths' => [32], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_status'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['status'], - 'lengths' => [32], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_requestMethod'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['requestMethod'], - 'lengths' => [128], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_requestPath'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['requestPath'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_deployment'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['deploymentId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_responseStatusCode'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['responseStatusCode'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_duration'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['duration'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'variables' => [ - '$collection' => Database::METADATA, - '$id' => 'variables', - 'name' => 'variables', - 'attributes' => [ - [ - '$id' => ID::custom('resourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 100, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'key', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'value', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 8192, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'] - ], - [ - '$id' => ID::custom('secret'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => false, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => '_key_resourceInternalId', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [], - ], - [ - '$id' => '_key_resourceType', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceType'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_resourceId_resourceType', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceId', 'resourceType'], - 'lengths' => [Database::LENGTH_KEY, 100], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => '_key_uniqueKey', - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['resourceId', 'key', 'resourceType'], - 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY, 100], - 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC, Database::ORDER_ASC], - ], - [ - '$id' => '_key_key', - 'type' => Database::INDEX_KEY, - 'attributes' => ['key'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'migrations' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('migrations'), - 'name' => 'Migrations', - 'attributes' => [ - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('stage'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('source'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 8192, // reduce size - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('destination'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, // make true after patch script - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('credentials'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65536, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - [ - '$id' => ID::custom('resources'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => [], - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('statusCounters'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 3000, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('resourceData'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 131070, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('errors'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => '_key_status', - 'type' => Database::INDEX_KEY, - 'attributes' => ['status'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_stage', - 'type' => Database::INDEX_KEY, - 'attributes' => ['stage'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_source', - 'type' => Database::INDEX_KEY, - 'attributes' => ['source'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ] - ], - ], -], $commonCollections); - -$consoleCollections = array_merge([ - 'projects' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('projects'), - 'name' => 'Projects', - 'attributes' => [ - [ - '$id' => ID::custom('teamInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('teamId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('region'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('description'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('database'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('logo'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('url'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('version'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalName'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalCountry'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalState'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalCity'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalAddress'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('legalTaxId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'accessedAt', - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('services'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('apis'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('smtp'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - [ - '$id' => ID::custom('templates'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, // TODO make sure size fits - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('auths'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('oAuthProviders'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - [ - '$id' => ID::custom('platforms'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryPlatforms'], - ], - [ - '$id' => ID::custom('webhooks'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryWebhooks'], - ], - [ - '$id' => ID::custom('keys'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['subQueryKeys'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('pingCount'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('pingedAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [128], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_team'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['teamId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_pingCount'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['pingCount'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_pingedAt'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['pingedAt'], - 'lengths' => [], - 'orders' => [], - ] - ], - ], - - 'schedules' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('schedules'), - 'name' => 'schedules', - 'attributes' => [ - [ - '$id' => ID::custom('resourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 100, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceUpdatedAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('schedule'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 100, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('data'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65535, - 'signed' => true, - 'required' => false, - 'default' => new \stdClass(), - 'array' => false, - 'filters' => ['json', 'encrypt'], - ], - [ - '$id' => ID::custom('active'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => null, - 'array' => false, - ], - [ - '$id' => ID::custom('region'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 10, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_region_resourceType_resourceUpdatedAt'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['region', 'resourceType', 'resourceUpdatedAt'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_region_resourceType_projectId_resourceId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['region', 'resourceType', 'projectId', 'resourceId'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'platforms' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('platforms'), - 'name' => 'platforms', - 'attributes' => [ - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('key'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('store'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('hostname'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_project'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'keys' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('keys'), - 'name' => 'keys', - 'attributes' => [ - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('scopes'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('secret'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 512, // var_dump of \bin2hex(\random_bytes(128)) => string(256) doubling for encryption - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('expire'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('accessedAt'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('sdks'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_project'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_accessedAt', - 'type' => Database::INDEX_KEY, - 'attributes' => ['accessedAt'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'webhooks' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('webhooks'), - 'name' => 'webhooks', - 'attributes' => [ - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('url'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('httpUser'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('httpPass'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, // TODO will the length suffice after encryption? - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['encrypt'], - ], - [ - '$id' => ID::custom('security'), - 'type' => Database::VAR_BOOLEAN, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('events'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - [ - '$id' => ID::custom('signatureKey'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => true, - 'array' => false, - ], - [ - '$id' => ID::custom('logs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('attempts'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_project'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'certificates' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('certificates'), - 'name' => 'Certificates', - 'attributes' => [ - [ - '$id' => ID::custom('domain'), - 'type' => Database::VAR_STRING, - 'format' => '', - // The maximum total length of a domain name or number is 255 characters. - // https://datatracker.ietf.org/doc/html/rfc2821#section-4.5.3.1 - // https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.3.1.2 - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('issueDate'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('renewDate'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('attempts'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('logs'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 1000000, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('updated'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_domain'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['domain'], - 'lengths' => [255], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'realtime' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('realtime'), - 'name' => 'Realtime Connections', - 'attributes' => [ - [ - '$id' => ID::custom('container'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('timestamp'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('value'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], //TODO: use json filter - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_timestamp'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['timestamp'], - 'lengths' => [], - 'orders' => [Database::ORDER_DESC], - ], - ] - ], - - 'rules' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('rules'), - 'name' => 'Rules', - 'attributes' => [ - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('domain'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 100, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('status'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('certificateId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ] - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_domain'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['domain'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_resourceInternalId', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_resourceId', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_resourceType', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceType'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'installations' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('installations'), - 'name' => 'installations', - 'attributes' => [ - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerInstallationId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('organization'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('provider'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('personal'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => false, - 'array' => false, - ], - ], - 'indexes' => [ - - [ - '$id' => ID::custom('_key_projectInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerInstallationId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerInstallationId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'repositories' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('repositories'), - 'name' => 'repositories', - 'attributes' => [ - [ - '$id' => ID::custom('installationId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('installationInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerRepositoryId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('resourceId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('resourceType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('providerPullRequestIds'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => true, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_installationId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_installationInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerRepositoryId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerRepositoryId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_resourceId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_resourceInternalId', - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_resourceType'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['resourceType'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ] - ], - ], - - 'vcsComments' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('vcsComments'), - 'name' => 'vcsComments', - 'attributes' => [ - [ - '$id' => ID::custom('installationId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('installationInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('projectId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('projectInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('providerRepositoryId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('providerCommentId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('providerPullRequestId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - [ - '$id' => ID::custom('providerBranch'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [] - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_installationId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_installationInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['installationInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_projectId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['projectId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerRepositoryId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerRepositoryId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerPullRequestId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerPullRequestId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_providerBranch'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['providerBranch'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - ], - ], - - 'vcsCommentLocks' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('vcsCommentLocks'), - 'name' => 'vcsCommentLocks', - 'attributes' => [], - 'indexes' => [] - ], -], $commonCollections); - -$bucketCollections = [ - 'files' => [ - '$collection' => ID::custom('buckets'), - '$id' => ID::custom('files'), - '$name' => 'Files', - 'attributes' => [ - [ - 'array' => false, - '$id' => ID::custom('bucketId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'filters' => [], - ], - [ - 'array' => false, - '$id' => ID::custom('bucketInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('path'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('signature'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('mimeType'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('metadata'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 75000, // https://tools.ietf.org/html/rfc4288#section-4.2 - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['json'], - ], - [ - '$id' => ID::custom('sizeOriginal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 8, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('sizeActual'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 8, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('algorithm'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('comment'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLVersion'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 64, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLCipher'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 64, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLTag'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('openSSLIV'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 2048, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('chunksTotal'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('chunksUploaded'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_bucket'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['bucketId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_signature'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['signature'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_mimeType'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['mimeType'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_sizeOriginal'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['sizeOriginal'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_chunksTotal'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['chunksTotal'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_chunksUploaded'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['chunksUploaded'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ] - ], -]; - -$dbCollections = [ - 'collections' => [ - '$collection' => ID::custom('databases'), - '$id' => ID::custom('collections'), - 'name' => 'Collections', - 'attributes' => [ - [ - '$id' => ID::custom('databaseInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('databaseId'), - 'type' => Database::VAR_STRING, - 'signed' => true, - 'size' => Database::LENGTH_KEY, - 'format' => '', - 'filters' => [], - 'required' => true, - 'default' => null, - 'array' => false, - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'size' => 256, - 'required' => true, - 'signed' => true, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('enabled'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'default' => null, - 'array' => false, - ], - [ - '$id' => ID::custom('documentSecurity'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => true, - 'default' => null, - 'array' => false, - ], - [ - '$id' => ID::custom('attributes'), - 'type' => Database::VAR_STRING, - 'size' => 1000000, - 'required' => false, - 'signed' => true, - 'array' => false, - 'filters' => ['subQueryAttributes'], - ], - [ - '$id' => ID::custom('indexes'), - 'type' => Database::VAR_STRING, - 'size' => 1000000, - 'required' => false, - 'signed' => true, - 'array' => false, - 'filters' => ['subQueryIndexes'], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_fulltext_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [256], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_enabled'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['enabled'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_documentSecurity'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['documentSecurity'], - 'lengths' => [], - 'orders' => [Database::ORDER_ASC], - ], - ], - ] -]; - - $collections = [ - 'projects' => $projectCollections, - 'console' => $consoleCollections, - 'buckets' => $bucketCollections, - 'databases' => $dbCollections + 'buckets' => $buckets, + 'databases' => $databases, + 'projects' => array_merge($projects, $common), + 'console' => array_merge($platform, $common), + 'logs' => $logs, ]; return $collections; diff --git a/app/config/collections/common.php b/app/config/collections/common.php new file mode 100644 index 0000000000..f006a01d1e --- /dev/null +++ b/app/config/collections/common.php @@ -0,0 +1,2647 @@ + [ + '$collection' => Database::METADATA, + '$id' => 'cache', + 'name' => 'Cache', + 'attributes' => [ + [ + '$id' => 'resource', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'resourceType', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mimeType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'accessedAt', + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => 'signature', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => '_key_resource', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resource'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'users' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('users'), + 'name' => 'Users', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('email'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 320, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('phone'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, // leading '+' and 15 digitts maximum by E.164 format + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('labels'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('passwordHistory'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('password'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => 'hash', // Hashing algorithm used to hash the password + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => Auth::DEFAULT_ALGO, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('hashOptions'), // Configuration of hashing algorithm + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => Auth::DEFAULT_ALGO_OPTIONS, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('passwordUpdate'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('prefs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => new \stdClass(), + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('registration'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('emailVerification'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('phoneVerification'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('reset'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mfa'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mfaRecoveryCodes'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('authenticators'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryAuthenticators'], + ], + [ + '$id' => ID::custom('sessions'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQuerySessions'], + ], + [ + '$id' => ID::custom('tokens'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryTokens'], + ], + [ + '$id' => ID::custom('challenges'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryChallenges'], + ], + [ + '$id' => ID::custom('memberships'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryMemberships'], + ], + [ + '$id' => ID::custom('targets'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryTargets'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['userSearch'], + ], + [ + '$id' => ID::custom('accessedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_email'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['email'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_phone'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['phone'], + 'lengths' => [16], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_status'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['status'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_passwordUpdate'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['passwordUpdate'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_registration'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['registration'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_emailVerification'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['emailVerification'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_phoneVerification'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['phoneVerification'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'tokens' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('tokens'), + 'name' => 'Tokens', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('secret'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('expire'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('userAgent'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('ip'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 45, // https://stackoverflow.com/a/166157/2299554 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_user'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'authenticators' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('authenticators'), + 'name' => 'Authenticators', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('verified'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => false, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('data'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_userInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'challenges' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('challenges'), + 'name' => 'Challenges', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('token'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], [ + '$id' => ID::custom('code'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 512, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], [ + '$id' => ID::custom('expire'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_user'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'sessions' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('sessions'), + 'name' => 'Sessions', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('provider'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerUid'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerAccessToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('providerAccessTokenExpiry'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('providerRefreshToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('secret'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 512, // https://www.tutorialspoint.com/how-long-is-the-sha256-hash-in-mysql (512 for encryption) + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('userAgent'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('ip'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 45, // https://stackoverflow.com/a/166157/2299554 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('countryCode'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('osCode'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('osName'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('osVersion'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientCode'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientName'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientVersion'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientEngine'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('clientEngineVersion'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deviceName'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deviceBrand'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deviceModel'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('factors'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('expire'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('mfaUpdatedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_provider_providerUid'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['provider', 'providerUid'], + 'lengths' => [128, 128], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_user'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'identities' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('identities'), + 'name' => 'Identities', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('provider'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerUid'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, // Decrease to 128 as in index length? + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerEmail'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 320, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerAccessToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('providerAccessTokenExpiry'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('providerRefreshToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + // Used to store data from provider that may or may not be sensitive + '$id' => ID::custom('secrets'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_userInternalId_provider_providerUid'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['userInternalId', 'provider', 'providerUid'], + 'lengths' => [11, 128, 128], // providerUid is length 2000! + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_provider_providerUid'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['provider', 'providerUid'], + 'lengths' => [128, 128], // providerUid is length 2000! + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_userId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_userInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_provider'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['provider'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerUid'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerUid'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerEmail'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerEmail'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerAccessTokenExpiry'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerAccessTokenExpiry'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'teams' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('teams'), + 'name' => 'Teams', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('total'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('prefs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => new \stdClass(), + 'array' => false, + 'filters' => ['json'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_total'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['total'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'memberships' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('memberships'), + 'name' => 'Memberships', + 'attributes' => [ + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('teamInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('teamId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('roles'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('invited'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('joined'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('confirm'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('secret'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_unique'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['teamInternalId', 'userInternalId'], + 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_user'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_team'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['teamInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_userId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_teamId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['teamId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_invited'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['invited'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_joined'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['joined'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_confirm'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['confirm'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_roles'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['roles'], + 'lengths' => [128], + 'orders' => [], + ], + ], + ], + + 'buckets' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('buckets'), + 'name' => 'Buckets', + 'attributes' => [ + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 128, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('fileSecurity'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 1, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('maximumFileSize'), + 'type' => Database::VAR_INTEGER, + 'signed' => false, + 'size' => 8, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('allowedFileExtensions'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 64, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => true, + ], + [ + '$id' => 'compression', + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 10, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('encryption'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('antivirus'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_fulltext_name'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['name'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_enabled'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_fileSecurity'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['fileSecurity'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_maximumFileSize'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['maximumFileSize'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_encryption'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['encryption'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_antivirus'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['antivirus'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ] + ], + + 'stats' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('stats'), + 'name' => 'Stats', + 'attributes' => [ + [ + '$id' => ID::custom('metric'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('region'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('value'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 8, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('time'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('period'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 4, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_time'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['time'], + 'lengths' => [], + 'orders' => [Database::ORDER_DESC], + ], + [ + '$id' => ID::custom('_key_period_time'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['period', 'time'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_metric_period_time'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['metric', 'period', 'time'], + 'lengths' => [], + 'orders' => [Database::ORDER_DESC], + ], + ], + ], + + 'providers' => [ + '$collection' => ID::custom(DATABASE::METADATA), + '$id' => ID::custom('providers'), + 'name' => 'Providers', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('provider'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'default' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('credentials'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + [ + '$id' => ID::custom('options'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => ['providerSearch'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_provider'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['provider'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['name'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_type'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['type'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_enabled_type'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled', 'type'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ] + ], + ], + + 'messages' => [ + '$collection' => ID::custom(DATABASE::METADATA), + '$id' => ID::custom('messages'), + 'name' => 'Messages', + 'attributes' => [ + [ + '$id' => ID::custom('providerType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => 'processing', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('data'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('topics'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 21845, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('users'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 21845, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('targets'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 21845, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduledAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('scheduleInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduleId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deliveredAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('deliveryErrors'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('deliveredTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => ['messageSearch'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'topics' => [ + '$collection' => ID::custom(DATABASE::METADATA), + '$id' => ID::custom('topics'), + 'name' => 'Topics', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('subscribe'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('emailTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('smsTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('pushTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('targets'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryTopicTargets'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => ['topicSearch'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['name'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'subscribers' => [ + '$collection' => ID::custom(DATABASE::METADATA), + '$id' => ID::custom('subscribers'), + 'name' => 'Subscribers', + 'attributes' => [ + [ + '$id' => ID::custom('targetId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('targetInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('topicId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('topicInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_targetId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['targetId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_targetInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['targetInternalId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_userId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_userInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_topicId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['topicId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_topicInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['topicInternalId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_unique_target_topic'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['targetInternalId', 'topicInternalId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'targets' => [ + '$collection' => ID::custom(DATABASE::METADATA), + '$id' => ID::custom('targets'), + 'name' => 'Targets', + 'attributes' => [ + [ + '$id' => ID::custom('userId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('userInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('sessionId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('sessionInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('identifier'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('expired'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => false, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_userId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userId'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_userInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['userInternalId'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_providerInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerInternalId'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_identifier'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['identifier'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + // note that this is not required for console & projects. + 'files' => [ + '$collection' => ID::custom('buckets'), + '$id' => ID::custom('files'), + '$name' => 'Files', + 'attributes' => [ + [ + 'array' => false, + '$id' => ID::custom('bucketId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('bucketInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('path'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('signature'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('mimeType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('metadata'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 75000, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('sizeOriginal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 8, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('sizeActual'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 8, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('algorithm'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('comment'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLVersion'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 64, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLCipher'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 64, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLTag'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('openSSLIV'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('chunksTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('chunksUploaded'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'transformedAt', + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_bucket'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['bucketId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_signature'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['signature'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_mimeType'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['mimeType'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_sizeOriginal'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['sizeOriginal'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_chunksTotal'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['chunksTotal'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_chunksUploaded'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['chunksUploaded'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_transformedAt'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['transformedAt'], + 'lengths' => [], + 'orders' => [], + ] + ] + ], +]; diff --git a/app/config/collections/databases.php b/app/config/collections/databases.php new file mode 100644 index 0000000000..995caecb7f --- /dev/null +++ b/app/config/collections/databases.php @@ -0,0 +1,126 @@ + [ + '$collection' => ID::custom('databases'), + '$id' => ID::custom('collections'), + 'name' => 'Collections', + 'attributes' => [ + [ + '$id' => ID::custom('databaseInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('databaseId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => true, + 'default' => null, + 'array' => false, + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'size' => 256, + 'required' => true, + 'signed' => true, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'default' => null, + 'array' => false, + ], + [ + '$id' => ID::custom('documentSecurity'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'default' => null, + 'array' => false, + ], + [ + '$id' => ID::custom('attributes'), + 'type' => Database::VAR_STRING, + 'size' => 1000000, + 'required' => false, + 'signed' => true, + 'array' => false, + 'filters' => ['subQueryAttributes'], + ], + [ + '$id' => ID::custom('indexes'), + 'type' => Database::VAR_STRING, + 'size' => 1000000, + 'required' => false, + 'signed' => true, + 'array' => false, + 'filters' => ['subQueryIndexes'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_enabled'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_documentSecurity'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['documentSecurity'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ] +]; diff --git a/app/config/collections/logs.php b/app/config/collections/logs.php new file mode 100644 index 0000000000..069dcf5a4b --- /dev/null +++ b/app/config/collections/logs.php @@ -0,0 +1,94 @@ + ID::custom(Database::METADATA), + '$id' => ID::custom('stats'), + 'name' => 'stats', + 'attributes' => [ + [ + '$id' => ID::custom('metric'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('region'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('value'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 8, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('time'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('period'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 4, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_time'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['time'], + 'lengths' => [], + 'orders' => [Database::ORDER_DESC], + ], + [ + '$id' => ID::custom('_key_period_time'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['period', 'time'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_metric_period_time'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['metric', 'period', 'time'], + 'lengths' => [], + 'orders' => [Database::ORDER_DESC], + ], + ], +]; + +return $logsCollection; diff --git a/app/config/collections/platform.php b/app/config/collections/platform.php new file mode 100644 index 0000000000..6a26054636 --- /dev/null +++ b/app/config/collections/platform.php @@ -0,0 +1,1733 @@ + [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('projects'), + 'name' => 'Projects', + 'attributes' => [ + [ + '$id' => ID::custom('teamInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('teamId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('region'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('description'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('database'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('logo'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('url'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('version'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalName'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalCountry'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalState'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalCity'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalAddress'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('legalTaxId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'accessedAt', + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('services'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('apis'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('smtp'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + [ + '$id' => ID::custom('templates'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, // TODO make sure size fits + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('auths'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('oAuthProviders'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + [ + '$id' => ID::custom('platforms'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryPlatforms'], + ], + [ + '$id' => ID::custom('webhooks'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryWebhooks'], + ], + [ + '$id' => ID::custom('keys'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryKeys'], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('pingCount'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('pingedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_team'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['teamId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_pingCount'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['pingCount'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_pingedAt'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['pingedAt'], + 'lengths' => [], + 'orders' => [], + ] + ], + ], + + 'schedules' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('schedules'), + 'name' => 'schedules', + 'attributes' => [ + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 100, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceUpdatedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('schedule'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 100, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('data'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => false, + 'default' => new \stdClass(), + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + [ + '$id' => ID::custom('active'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => null, + 'array' => false, + ], + [ + '$id' => ID::custom('region'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 10, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_region_resourceType_resourceUpdatedAt'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['region', 'resourceType', 'resourceUpdatedAt'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_region_resourceType_projectId_resourceId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['region', 'resourceType', 'projectId', 'resourceId'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'platforms' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('platforms'), + 'name' => 'platforms', + 'attributes' => [ + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('key'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('store'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('hostname'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_project'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'keys' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('keys'), + 'name' => 'keys', + 'attributes' => [ + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('scopes'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('secret'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 512, // var_dump of \bin2hex(\random_bytes(128)) => string(256) doubling for encryption + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('expire'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('accessedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('sdks'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_project'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_accessedAt', + 'type' => Database::INDEX_KEY, + 'attributes' => ['accessedAt'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'webhooks' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('webhooks'), + 'name' => 'webhooks', + 'attributes' => [ + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('url'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('httpUser'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('httpPass'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, // TODO will the length suffice after encryption? + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('security'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('events'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('signatureKey'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('logs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('attempts'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_project'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'certificates' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('certificates'), + 'name' => 'Certificates', + 'attributes' => [ + [ + '$id' => ID::custom('domain'), + 'type' => Database::VAR_STRING, + 'format' => '', + // The maximum total length of a domain name or number is 255 characters. + // https://datatracker.ietf.org/doc/html/rfc2821#section-4.5.3.1 + // https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.3.1.2 + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('issueDate'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('renewDate'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('attempts'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('logs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('updated'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_domain'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['domain'], + 'lengths' => [255], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'realtime' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('realtime'), + 'name' => 'Realtime Connections', + 'attributes' => [ + [ + '$id' => ID::custom('container'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('timestamp'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('value'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], //TODO: use json filter + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_timestamp'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['timestamp'], + 'lengths' => [], + 'orders' => [Database::ORDER_DESC], + ], + ] + ], + + 'rules' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('rules'), + 'name' => 'Rules', + 'attributes' => [ + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('domain'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), // 'api', 'redirect', 'deployment' (site or function) + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 32, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('trigger'), // 'manual', 'deployment', '' (empty) + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 32, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('redirectUrl'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('redirectStatusCode'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentResourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 32, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentResourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentResourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentVcsProviderBranch'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('certificateId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('owner'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => '', // "Appwrite" or empty string + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('region'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_domain'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['domain'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_type', + 'type' => Database::INDEX_KEY, + 'attributes' => ['type'], + 'lengths' => [32], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_trigger', + 'type' => Database::INDEX_KEY, + 'attributes' => ['trigger'], + 'lengths' => [32], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_deploymentResourceType', + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentResourceType'], + 'lengths' => [32], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_deploymentResourceId', + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentResourceId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_deploymentResourceInternalId', + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentResourceInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_deploymentId', + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_deploymentInternalId', + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_deploymentVcsProviderBranch', + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentVcsProviderBranch'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_owner'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['owner'], + 'lengths' => [16], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_region'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['region'], + 'lengths' => [16], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'installations' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('installations'), + 'name' => 'installations', + 'attributes' => [ + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerInstallationId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('organization'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('provider'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('personal'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('personalAccessToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('personalAccessTokenExpiry'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('personalRefreshToken'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], + ], + ], + 'indexes' => [ + + [ + '$id' => ID::custom('_key_projectInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerInstallationId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerInstallationId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'repositories' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('repositories'), + 'name' => 'repositories', + 'attributes' => [ + [ + '$id' => ID::custom('installationId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('installationInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerRepositoryId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('providerPullRequestIds'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_installationId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_installationInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerRepositoryId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerRepositoryId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_resourceId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_resourceInternalId', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_resourceType'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceType'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'vcsComments' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('vcsComments'), + 'name' => 'vcsComments', + 'attributes' => [ + [ + '$id' => ID::custom('installationId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('installationInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('projectId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('projectInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerRepositoryId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('providerCommentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('providerPullRequestId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + [ + '$id' => ID::custom('providerBranch'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [] + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_installationId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_installationInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_projectId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['projectId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerRepositoryId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerRepositoryId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerPullRequestId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerPullRequestId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerBranch'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerBranch'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'vcsCommentLocks' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('vcsCommentLocks'), + 'name' => 'vcsCommentLocks', + 'attributes' => [], + 'indexes' => [] + ] +]; diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php new file mode 100644 index 0000000000..ae27e81fcc --- /dev/null +++ b/app/config/collections/projects.php @@ -0,0 +1,2405 @@ + [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('databases'), + 'name' => 'Databases', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'size' => 256, + 'required' => true, + 'signed' => true, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('originalId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => null, + 'array' => false, + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'attributes' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('attributes'), + 'name' => 'Attributes', + 'attributes' => [ + [ + '$id' => ID::custom('databaseInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('databaseId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => false, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('collectionInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('collectionId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('key'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('error'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('size'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('required'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('default'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['casting'], + ], + [ + '$id' => ID::custom('signed'), + 'type' => Database::VAR_BOOLEAN, + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('array'), + 'type' => Database::VAR_BOOLEAN, + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('format'), + 'type' => Database::VAR_STRING, + 'size' => 64, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('formatOptions'), + 'type' => Database::VAR_STRING, + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => new stdClass(), + 'array' => false, + 'filters' => ['json', 'range', 'enum'], + ], + [ + '$id' => ID::custom('filters'), + 'type' => Database::VAR_STRING, + 'size' => 64, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('options'), + 'type' => Database::VAR_STRING, + 'size' => 16384, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_db_collection'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['databaseInternalId', 'collectionInternalId'], + 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + ], + ], + + 'indexes' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('indexes'), + 'name' => 'Indexes', + 'attributes' => [ + [ + '$id' => ID::custom('databaseInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('databaseId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => false, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('collectionInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('collectionId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('key'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('error'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('attributes'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('lengths'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('orders'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 4, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_db_collection'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['databaseInternalId', 'collectionInternalId'], + 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + ], + ], + + 'functions' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('functions'), + 'name' => 'Functions', + 'attributes' => [ + [ + '$id' => ID::custom('execute'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('live'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('installationId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('installationInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerRepositoryId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('repositoryId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('repositoryInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerBranch'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRootDirectory'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerSilentMode'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('logging'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('runtime'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentCreatedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('latestDeploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('latestDeploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('latestDeploymentCreatedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('latestDeploymentStatus'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('vars'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryVariables'], + ], + [ + '$id' => ID::custom('varsProject'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryProjectVariables'], + ], + [ + '$id' => ID::custom('events'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduleInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduleId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('schedule'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('timeout'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('version'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 8, + 'signed' => true, + 'required' => false, + 'default' => 'v5', + 'array' => false, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('entrypoint'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('commands'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('specification'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => false, + 'required' => false, + 'default' => APP_COMPUTE_SPECIFICATION_DEFAULT, + 'filters' => [], + ], + [ + '$id' => ID::custom('scopes'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_enabled'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_installationId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_installationInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerRepositoryId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerRepositoryId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_repositoryId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['repositoryId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_repositoryInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['repositoryInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_runtime'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['runtime'], + 'lengths' => [64], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_deploymentId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentId'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + + 'sites' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('sites'), + 'name' => 'Sites', + 'attributes' => [ + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('enabled'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('live'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('installationId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('installationInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerRepositoryId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('repositoryId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('repositoryInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerBranch'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRootDirectory'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerSilentMode'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('logging'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => true, + 'array' => false, + ], + [ + '$id' => ID::custom('framework'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('outputDirectory'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('buildCommand'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('installCommand'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('fallbackFile'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentCreatedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('deploymentScreenshotLight'), // File ID from 'screenshots' Console bucket + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 32, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentScreenshotDark'), // File ID from 'screenshots' Console bucket + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 32, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('latestDeploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('latestDeploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('latestDeploymentCreatedAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('latestDeploymentStatus'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('vars'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryVariables'], + ], + [ + '$id' => ID::custom('varsProject'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['subQueryProjectVariables'], + ], + [ + '$id' => ID::custom('timeout'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('specification'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => false, + 'required' => false, + 'default' => APP_COMPUTE_SPECIFICATION_DEFAULT, + 'filters' => [], + ], + [ + '$id' => ID::custom('buildRuntime'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => true, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('adapter'), // ssr or static; named this way as it's a term in SSR frameworks + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [256], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_enabled'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['enabled'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_installationId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_installationInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['installationInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_providerRepositoryId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['providerRepositoryId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_repositoryId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['repositoryId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_repositoryInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['repositoryInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_framework'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['framework'], + 'lengths' => [64], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_deploymentId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentId'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ] + ], + ], + 'deployments' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('deployments'), + 'name' => 'Deployments', + 'attributes' => [ + [ + '$id' => ID::custom('resourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('entrypoint'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('buildCommands'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('buildOutput'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('sourcePath'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 32, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('installationId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('installationInternalId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRepositoryId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('repositoryId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('repositoryInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('providerRepositoryName'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRepositoryOwner'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRepositoryUrl'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommitHash'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommitAuthorUrl'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommitAuthor'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommitMessage'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommitUrl'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerBranch'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerBranchUrl'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerRootDirectory'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => Database::LENGTH_KEY, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('providerCommentId'), + 'type' => Database::VAR_STRING, + 'signed' => true, + 'size' => 2048, + 'format' => '', + 'filters' => [], + 'required' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('sourceSize'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('sourceMetadata'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, // https://tools.ietf.org/html/rfc4288#section-4.2 + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('sourceChunksTotal'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('sourceChunksUploaded'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('activate'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => false, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('screenshotLight'), // File ID from 'screenshots' Console bucket + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 32, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('screenshotDark'), // File ID from 'screenshots' Console bucket + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 32, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('buildStartAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('buildEndAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('buildDuration'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('buildSize'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('totalSize'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16, + 'signed' => true, + 'required' => true, + 'default' => 'waiting', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('buildPath'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('buildLogs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('adapter'), // ssr or static; named this way as it's a term in SSR frameworks + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => '', + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('fallbackFile'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ] + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_resource'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceId'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_resource_type'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceType'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_sourceSize'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['sourceSize'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_buildSize'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['buildSize'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_totalSize'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['totalSize'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_buildDuration'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['buildDuration'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_activate'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['activate'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_type'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['type'], + 'lengths' => [32], + 'orders' => [Database::ORDER_ASC], + ], [ + '$id' => ID::custom('_key_status'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['status'], + 'lengths' => [16], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'executions' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('executions'), + 'name' => 'Executions', + 'attributes' => [ + [ + '$id' => ID::custom('resourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('deploymentId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('trigger'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('duration'), + 'type' => Database::VAR_FLOAT, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('errors'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('logs'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 1000000, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('requestMethod'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 128, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + 'array' => false, + '$id' => ID::custom('requestPath'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 2048, + 'signed' => true, + 'required' => false, + 'default' => null, + 'filters' => [], + ], + [ + '$id' => ID::custom('requestHeaders'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('responseStatusCode'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('responseHeaders'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('scheduledAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('scheduleInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduleId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_resource'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceInternalId', 'resourceType', 'resourceId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_trigger'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['trigger'], + 'lengths' => [32], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_status'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['status'], + 'lengths' => [32], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_requestMethod'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['requestMethod'], + 'lengths' => [128], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_requestPath'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['requestPath'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_deployment'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['deploymentId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_responseStatusCode'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['responseStatusCode'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_duration'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['duration'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'variables' => [ + '$collection' => Database::METADATA, + '$id' => 'variables', + 'name' => 'variables', + 'attributes' => [ + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 100, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'key', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'value', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 8192, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'] + ], + [ + '$id' => ID::custom('secret'), + 'type' => Database::VAR_BOOLEAN, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => false, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_resourceInternalId', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [], + ], + [ + '$id' => '_key_resourceType', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceType'], + 'lengths' => [], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_resourceId_resourceType', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceId', 'resourceType'], + 'lengths' => [Database::LENGTH_KEY, 100], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => '_key_uniqueKey', + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['resourceId', 'key', 'resourceType'], + 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY, 100], + 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC, Database::ORDER_ASC], + ], + [ + '$id' => '_key_key', + 'type' => Database::INDEX_KEY, + 'attributes' => ['key'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'migrations' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('migrations'), + 'name' => 'Migrations', + 'attributes' => [ + [ + '$id' => ID::custom('status'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('stage'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('source'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 8192, // reduce size + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('destination'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, // make true after patch script + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('credentials'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65536, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json', 'encrypt'], + ], + [ + '$id' => ID::custom('options'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65536, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('resources'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => [], + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('statusCounters'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 3000, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('resourceData'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 131070, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => ['json'], + ], + [ + '$id' => ID::custom('errors'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65535, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('resourceType'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_status', + 'type' => Database::INDEX_KEY, + 'attributes' => ['status'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_stage', + 'type' => Database::INDEX_KEY, + 'attributes' => ['stage'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_source', + 'type' => Database::INDEX_KEY, + 'attributes' => ['source'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => '_key_resource_id', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_DESC], + ], + [ + '$id' => ID::custom('_fulltext_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ] + ], + ], +]; diff --git a/app/config/console.php b/app/config/console.php new file mode 100644 index 0000000000..e37c9b7836 --- /dev/null +++ b/app/config/console.php @@ -0,0 +1,53 @@ + ID::custom('console'), + '$internalId' => ID::custom('console'), + 'name' => 'Appwrite', + '$collection' => ID::custom('projects'), + 'description' => 'Appwrite core engine', + 'logo' => '', + 'teamId' => null, + 'webhooks' => [], + 'keys' => [], + 'platforms' => [ + [ + '$collection' => ID::custom('platforms'), + 'name' => 'Localhost', + 'type' => Origin::CLIENT_TYPE_WEB, + 'hostname' => 'localhost', + ], // Current host is added on app init + ], + 'region' => 'fra', + 'legalName' => '', + 'legalCountry' => '', + 'legalState' => '', + 'legalCity' => '', + 'legalAddress' => '', + 'legalTaxId' => '', + 'auths' => [ + 'mockNumbers' => [], + 'invites' => System::getEnv('_APP_CONSOLE_INVITES', 'enabled') === 'enabled', + 'limit' => (System::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled') === 'enabled') ? 1 : 0, // limit signup to 1 user + 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG, // 1 Year in seconds + 'sessionAlerts' => System::getEnv('_APP_CONSOLE_SESSION_ALERTS', 'disabled') === 'enabled' + ], + 'authWhitelistEmails' => (!empty(System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [], + 'authWhitelistIPs' => (!empty(System::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [], + 'oAuthProviders' => [ + 'githubEnabled' => true, + 'githubSecret' => System::getEnv('_APP_CONSOLE_GITHUB_SECRET', ''), + 'githubAppid' => System::getEnv('_APP_CONSOLE_GITHUB_APP_ID', '') + ], +]; + +return $console; diff --git a/app/config/errors.php b/app/config/errors.php index 3afec4faaf..2c1bda995d 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -349,11 +349,6 @@ return [ 'description' => 'Team with the requested ID could not be found.', 'code' => 404, ], - Exception::TEAM_INVITE_ALREADY_EXISTS => [ - 'name' => Exception::TEAM_INVITE_ALREADY_EXISTS, - 'description' => 'User has already been invited or is already a member of this team', - 'code' => 409, - ], Exception::TEAM_INVITE_NOT_FOUND => [ 'name' => Exception::TEAM_INVITE_NOT_FOUND, 'description' => 'The requested team invitation could not be found.', @@ -361,7 +356,7 @@ return [ ], Exception::TEAM_INVALID_SECRET => [ 'name' => Exception::TEAM_INVALID_SECRET, - 'description' => 'The team invitation secret is invalid. Please request a new invitation and try again.', + 'description' => 'The team invitation secret is invalid. Please request a new invitation and try again.', 'code' => 401, ], Exception::TEAM_MEMBERSHIP_MISMATCH => [ @@ -380,6 +375,13 @@ return [ 'code' => 409, ], + /** Console */ + Exception::RESOURCE_ALREADY_EXISTS => [ + 'name' => Exception::RESOURCE_ALREADY_EXISTS, + 'description' => 'Resource with the requested ID already exists. Please choose a different ID and try again.', + 'code' => 409, + ], + /** Membership */ Exception::MEMBERSHIP_NOT_FOUND => [ 'name' => Exception::MEMBERSHIP_NOT_FOUND, @@ -525,7 +527,7 @@ return [ 'code' => 404, ], Exception::FUNCTION_ENTRYPOINT_MISSING => [ - 'name' => Exception::FUNCTION_RUNTIME_UNSUPPORTED, + 'name' => Exception::FUNCTION_ENTRYPOINT_MISSING, 'description' => 'Entrypoint for your Appwrite Function is missing. Please specify it when making deployment or update the entrypoint under your function\'s "Settings" > "Configuration" > "Entrypoint".', 'code' => 404, ], @@ -539,6 +541,28 @@ return [ 'description' => 'Function Template with the requested ID could not be found.', 'code' => 404, ], + Exception::FUNCTION_RUNTIME_NOT_DETECTED => [ + 'name' => Exception::FUNCTION_RUNTIME_NOT_DETECTED, + 'description' => 'Function runtime could not be detected.', + 'code' => 400, + ], + Exception::FUNCTION_EXECUTE_PERMISSION_MISSING => [ + 'name' => Exception::FUNCTION_EXECUTE_PERMISSION_MISSING, + 'description' => 'To execute function using domain, execute permissions must include "any" or "guests".', + 'code' => 401, + ], + + /** Sites */ + Exception::SITE_NOT_FOUND => [ + 'name' => Exception::SITE_NOT_FOUND, + 'description' => 'Site with the requested ID could not be found.', + 'code' => 404, + ], + Exception::SITE_TEMPLATE_NOT_FOUND => [ + 'name' => Exception::SITE_TEMPLATE_NOT_FOUND, + 'description' => 'Site Template with the requested ID could not be found.', + 'code' => 404, + ], /** Builds */ Exception::BUILD_NOT_FOUND => [ @@ -561,6 +585,16 @@ return [ 'description' => 'Build with the requested ID is already completed and cannot be canceled.', 'code' => 400, ], + Exception::BUILD_CANCELED => [ + 'name' => Exception::BUILD_CANCELED, + 'description' => 'Build with the requested ID has been canceled.', + 'code' => 400, + ], + Exception::BUILD_FAILED => [ + 'name' => Exception::BUILD_FAILED, + 'description' => 'Build with the requested ID failed. Please check the logs for more information.', + 'code' => 400, + ], /** Deployments */ Exception::DEPLOYMENT_NOT_FOUND => [ @@ -582,6 +616,13 @@ return [ 'code' => 400, ], + /** Logs */ + Exception::LOG_NOT_FOUND => [ + 'name' => Exception::LOG_NOT_FOUND, + 'description' => 'Log with the requested ID could not be found.', + 'code' => 404, + ], + /** Databases */ Exception::DATABASE_NOT_FOUND => [ 'name' => Exception::DATABASE_NOT_FOUND, @@ -686,7 +727,7 @@ return [ ], Exception::ATTRIBUTE_LIMIT_EXCEEDED => [ 'name' => Exception::ATTRIBUTE_LIMIT_EXCEEDED, - 'description' => 'The maximum number of attributes has been reached.', + 'description' => 'The maximum number or size of attributes for this collection has been reached.', 'code' => 400, ], Exception::ATTRIBUTE_VALUE_INVALID => [ @@ -731,6 +772,11 @@ return [ 'description' => 'Index invalid.', 'code' => 400, ], + Exception::INDEX_DEPENDENCY => [ + 'name' => Exception::INDEX_DEPENDENCY, + 'description' => 'Attribute cannot be renamed or deleted. Please remove the associated index first.', + 'code' => 409, + ], /** Project Errors */ Exception::PROJECT_NOT_FOUND => [ @@ -801,7 +847,7 @@ return [ Exception::RULE_VERIFICATION_FAILED => [ 'name' => Exception::RULE_VERIFICATION_FAILED, 'description' => 'Domain verification failed. Please check if your DNS records are correct and try again.', - 'code' => 401, + 'code' => 400, 'publish' => true ], Exception::PROJECT_SMTP_CONFIG_INVALID => [ @@ -844,6 +890,11 @@ return [ 'description' => 'Variable with the same ID already exists in this project. Try again with a different ID.', 'code' => 409, ], + Exception::VARIABLE_CANNOT_UNSET_SECRET => [ + 'name' => Exception::VARIABLE_CANNOT_UNSET_SECRET, + 'description' => 'Secret variables cannot be marked as non-secret. Please re-create the variable if this is your intention.', + 'code' => 400, + ], Exception::GRAPHQL_NO_QUERY => [ 'name' => Exception::GRAPHQL_NO_QUERY, 'description' => 'Param "query" is not optional.', diff --git a/app/config/events.php b/app/config/events.php index 5378502faf..0bfddf4f1f 100644 --- a/app/config/events.php +++ b/app/config/events.php @@ -217,6 +217,34 @@ return [ ], ] ], + 'sites' => [ + '$model' => Response::MODEL_SITE, + '$resource' => true, + '$description' => 'This event triggers on any sites event.', + 'deployments' => [ + '$model' => Response::MODEL_DEPLOYMENT, + '$resource' => true, + '$description' => 'This event triggers on any deployments event.', + 'create' => [ + '$description' => 'This event triggers when a deployment is created.', + ], + 'delete' => [ + '$description' => 'This event triggers when a deployment is deleted.' + ], + 'update' => [ + '$description' => 'This event triggers when a deployment is updated.' + ], + ], + 'create' => [ + '$description' => 'This event triggers when a site is created.' + ], + 'delete' => [ + '$description' => 'This event triggers when a site is deleted.', + ], + 'update' => [ + '$description' => 'This event triggers when a site is updated.', + ] + ], 'functions' => [ '$model' => Response::MODEL_FUNCTION, '$resource' => true, diff --git a/app/config/frameworks.php b/app/config/frameworks.php new file mode 100644 index 0000000000..afdf96145e --- /dev/null +++ b/app/config/frameworks.php @@ -0,0 +1,295 @@ + [ + 'key' => 'analog', + 'name' => 'Analog', + 'screenshotSleep' => 3000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'bash /usr/local/server/helpers/analog/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/analog/env.sh', + 'adapters' => [ + 'ssr' => [ + 'key' => 'ssr', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './dist/analog', + 'startCommand' => 'bash helpers/analog/server.sh', + ], + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './dist/analog/public', + 'startCommand' => 'bash helpers/server.sh', + 'fallbackFile' => 'index.html' + ] + ] + ], + 'angular' => [ + 'key' => 'angular', + 'name' => 'Angular', + 'screenshotSleep' => 3000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'bash /usr/local/server/helpers/angular/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/angular/env.sh', + 'adapters' => [ + 'ssr' => [ + 'key' => 'ssr', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './dist/angular', + 'startCommand' => 'bash helpers/angular/server.sh', + ], + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './dist/angular/browser', + 'startCommand' => 'bash helpers/server.sh', + 'fallbackFile' => 'index.csr.html' + ] + ] + ], + 'nextjs' => [ + 'key' => 'nextjs', + 'name' => 'Next.js', + 'screenshotSleep' => 3000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'bash /usr/local/server/helpers/next-js/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/next-js/env.sh', + 'adapters' => [ + 'ssr' => [ + 'key' => 'ssr', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './.next', + 'startCommand' => 'bash helpers/next-js/server.sh', + ], + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './out', + 'startCommand' => 'bash helpers/server.sh', + ] + ] + ], + 'react' => [ + 'key' => 'react', + 'name' => 'React', + 'screenshotSleep' => 3000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'adapters' => [ + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './dist', + 'startCommand' => 'bash helpers/server.sh', + 'fallbackFile' => 'index.html' + ] + ] + ], + 'nuxt' => [ + 'key' => 'nuxt', + 'name' => 'Nuxt', + 'screenshotSleep' => 3000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'bash /usr/local/server/helpers/nuxt/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/nuxt/env.sh', + 'adapters' => [ + 'ssr' => [ + 'key' => 'ssr', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './.output', + 'startCommand' => 'bash helpers/nuxt/server.sh', + ], + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run generate', + 'installCommand' => 'npm install', + 'outputDirectory' => './output/public', + 'startCommand' => 'bash helpers/server.sh', + ] + ] + ], + 'vue' => [ + 'key' => 'vue', + 'name' => 'Vue.js', + 'screenshotSleep' => 5000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'adapters' => [ + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './dist', + 'startCommand' => 'bash helpers/server.sh', + 'fallbackFile' => 'index.html' + ] + ] + ], + 'sveltekit' => [ + 'key' => 'sveltekit', + 'name' => 'SvelteKit', + 'screenshotSleep' => 3000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'bash /usr/local/server/helpers/sveltekit/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/sveltekit/env.sh', + 'adapters' => [ + 'ssr' => [ + 'key' => 'ssr', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './build', + 'startCommand' => 'bash helpers/sveltekit/server.sh', + ], + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './build', + 'startCommand' => 'bash helpers/server.sh', + ] + ] + ], + 'astro' => [ + 'key' => 'astro', + 'name' => 'Astro', + 'screenshotSleep' => 3000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'bash /usr/local/server/helpers/astro/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/astro/env.sh', + 'adapters' => [ + 'ssr' => [ + 'key' => 'ssr', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './dist', + 'startCommand' => 'bash helpers/astro/server.sh', + ], + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './dist', + 'startCommand' => 'bash helpers/server.sh', + ] + ] + ], + 'remix' => [ + 'key' => 'remix', + 'name' => 'Remix', + 'screenshotSleep' => 3000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'bundleCommand' => 'bash /usr/local/server/helpers/remix/bundle.sh', + 'envCommand' => 'source /usr/local/server/helpers/remix/env.sh', + 'adapters' => [ + 'ssr' => [ + 'key' => 'ssr', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './build', + 'startCommand' => 'bash helpers/remix/server.sh', + ], + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './build/client', + 'startCommand' => 'bash helpers/server.sh', + ] + ] + ], + 'lynx' => [ + 'key' => 'lynx', + 'name' => 'Lynx', + 'screenshotSleep' => 5000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'adapters' => [ + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './dist', + 'startCommand' => 'bash helpers/server.sh', + 'fallbackFile' => 'index.html' + ] + ] + ], + 'flutter' => [ + 'key' => 'flutter', + 'name' => 'Flutter', + 'screenshotSleep' => 5000, + 'buildRuntime' => 'flutter-3.29', + 'runtimes' => getVersions($templateRuntimes['FLUTTER']['versions'], 'flutter'), + 'adapters' => [ + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'flutter build web', + 'installCommand' => '', + 'outputDirectory' => './build/web', + 'startCommand' => 'bash helpers/server.sh', + ], + ], + ], + 'vite' => [ + 'key' => 'vite', + 'name' => 'Vite', + 'screenshotSleep' => 3000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'adapters' => [ + 'static' => [ + 'key' => 'static', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'outputDirectory' => './dist', + 'startCommand' => 'bash helpers/server.sh', + ], + ] + ], + 'other' => [ + 'key' => 'other', + 'name' => 'Other', + 'screenshotSleep' => 3000, + 'buildRuntime' => 'node-22', + 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), + 'adapters' => [ + 'static' => [ + 'key' => 'static', + 'buildCommand' => '', + 'installCommand' => '', + 'outputDirectory' => './', + 'startCommand' => 'bash helpers/server.sh', + ], + ] + ], +]; diff --git a/app/config/locale/continents.php b/app/config/locale/continents.php index 2f1ffc0a53..611c725ef1 100644 --- a/app/config/locale/continents.php +++ b/app/config/locale/continents.php @@ -1,11 +1,46 @@ [ + 'name' => 'Africa', + 'latitude' => 8.7832, + 'longitude' => 34.5085 + ], + 'AN' => [ + 'name' => 'Antarctica', + 'latitude' => -82.8628, + 'longitude' => 135.0000 + ], + 'AS' => [ + 'name' => 'Asia', + 'latitude' => 34.0479, + 'longitude' => 100.6197 + ], + 'EU' => [ + 'name' => 'Europe', + 'latitude' => 54.5260, + 'longitude' => 15.2551 + ], + 'NA' => [ + 'name' => 'North America', + 'latitude' => 54.5260, + 'longitude' => -105.2551 + ], + 'OC' => [ + 'name' => 'Oceania', + 'latitude' => -22.7359, + 'longitude' => 140.0188 + ], + 'SA' => [ + 'name' => 'South America', + 'latitude' => -8.7832, + 'longitude' => -55.4915 + ], ]; diff --git a/app/config/locale/countries.php b/app/config/locale/countries.php index bd2cbbbaaa..adfc5d76a6 100644 --- a/app/config/locale/countries.php +++ b/app/config/locale/countries.php @@ -1,209 +1,210 @@ ['name' => 'Afghanistan', 'latitude' => 33.0, 'longitude' => 66.0], + 'AO' => ['name' => 'Angola', 'latitude' => -12.5, 'longitude' => 18.5], + 'AL' => ['name' => 'Albania', 'latitude' => 41.0, 'longitude' => 20.0], + 'AD' => ['name' => 'Andorra', 'latitude' => 42.5, 'longitude' => 1.6], + 'AE' => ['name' => 'United Arab Emirates', 'latitude' => 24.0, 'longitude' => 54.0], + 'AR' => ['name' => 'Argentina', 'latitude' => -34.0, 'longitude' => -64.0], + 'AM' => ['name' => 'Armenia', 'latitude' => 40.0, 'longitude' => 45.0], + 'AG' => ['name' => 'Antigua and Barbuda', 'latitude' => 17.05, 'longitude' => -61.8], + 'AU' => ['name' => 'Australia', 'latitude' => -25.0, 'longitude' => 135.0], + 'AT' => ['name' => 'Austria', 'latitude' => 47.3, 'longitude' => 13.3], + 'AZ' => ['name' => 'Azerbaijan', 'latitude' => 40.5, 'longitude' => 47.5], + 'BI' => ['name' => 'Burundi', 'latitude' => -3.5, 'longitude' => 30.0], + 'BE' => ['name' => 'Belgium', 'latitude' => 50.8, 'longitude' => 4.0], + 'BJ' => ['name' => 'Benin', 'latitude' => 9.5, 'longitude' => 2.25], + 'BF' => ['name' => 'Burkina Faso', 'latitude' => 13.0, 'longitude' => -2.0], + 'BD' => ['name' => 'Bangladesh', 'latitude' => 24.0, 'longitude' => 90.0], + 'BG' => ['name' => 'Bulgaria', 'latitude' => 43.0, 'longitude' => 25.0], + 'BH' => ['name' => 'Bahrain', 'latitude' => 26.0, 'longitude' => 50.5], + 'BS' => ['name' => 'Bahamas', 'latitude' => 24.25, 'longitude' => -76.0], + 'BA' => ['name' => 'Bosnia and Herzegovina', 'latitude' => 44.0, 'longitude' => 18.0], + 'BY' => ['name' => 'Belarus', 'latitude' => 53.0, 'longitude' => 28.0], + 'BZ' => ['name' => 'Belize', 'latitude' => 17.25, 'longitude' => -88.75], + 'BO' => ['name' => 'Bolivia', 'latitude' => -17.0, 'longitude' => -65.0], + 'BR' => ['name' => 'Brazil', 'latitude' => -10.0, 'longitude' => -55.0], + 'BB' => ['name' => 'Barbados', 'latitude' => 13.17, 'longitude' => -59.53], + 'BN' => ['name' => 'Brunei', 'latitude' => 4.5, 'longitude' => 114.67], + 'BT' => ['name' => 'Bhutan', 'latitude' => 27.5, 'longitude' => 90.5], + 'BW' => ['name' => 'Botswana', 'latitude' => -22.0, 'longitude' => 24.0], + 'CF' => ['name' => 'Central African Republic', 'latitude' => 7.0, 'longitude' => 21.0], + 'CA' => ['name' => 'Canada', 'latitude' => 60.0, 'longitude' => -95.0], + 'CH' => ['name' => 'Switzerland', 'latitude' => 47.0, 'longitude' => 8.0], + 'CL' => ['name' => 'Chile', 'latitude' => -30.0, 'longitude' => -71.0], + 'CN' => ['name' => 'China', 'latitude' => 35.0, 'longitude' => 105.0], + 'CI' => ['name' => 'Côte d\'Ivoire', 'latitude' => 8.0, 'longitude' => -5.0], + 'CM' => ['name' => 'Cameroon', 'latitude' => 6.0, 'longitude' => 12.0], + 'CD' => ['name' => 'Democratic Republic of the Congo', 'latitude' => -2.5, 'longitude' => 23.5], + 'CG' => ['name' => 'Republic of the Congo', 'latitude' => -1.0, 'longitude' => 15.0], + 'CO' => ['name' => 'Colombia', 'latitude' => 4.0, 'longitude' => -72.0], + 'KM' => ['name' => 'Comoros', 'latitude' => -12.17, 'longitude' => 44.25], + 'CV' => ['name' => 'Cape Verde', 'latitude' => 16.0, 'longitude' => -24.0], + 'CR' => ['name' => 'Costa Rica', 'latitude' => 10.0, 'longitude' => -84.0], + 'CU' => ['name' => 'Cuba', 'latitude' => 21.5, 'longitude' => -80.0], + 'CY' => ['name' => 'Cyprus', 'latitude' => 35.0, 'longitude' => 33.0], + 'CZ' => ['name' => 'Czech Republic', 'latitude' => 49.75, 'longitude' => 15.5], + 'DE' => ['name' => 'Germany', 'latitude' => 51.0, 'longitude' => 9.0], + 'DJ' => ['name' => 'Djibouti', 'latitude' => 11.5, 'longitude' => 43.0], + 'DM' => ['name' => 'Dominica', 'latitude' => 15.42, 'longitude' => -61.33], + 'DK' => ['name' => 'Denmark', 'latitude' => 56.0, 'longitude' => 10.0], + 'DO' => ['name' => 'Dominican Republic', 'latitude' => 19.0, 'longitude' => -70.67], + 'DZ' => ['name' => 'Algeria', 'latitude' => 28.0, 'longitude' => 3.0], + 'EC' => ['name' => 'Ecuador', 'latitude' => -2.0, 'longitude' => -77.5], + 'EG' => ['name' => 'Egypt', 'latitude' => 27.0, 'longitude' => 30.0], + 'ER' => ['name' => 'Eritrea', 'latitude' => 15.0, 'longitude' => 39.0], + 'ES' => ['name' => 'Spain', 'latitude' => 40.0, 'longitude' => -4.0], + 'EE' => ['name' => 'Estonia', 'latitude' => 59.0, 'longitude' => 26.0], + 'ET' => ['name' => 'Ethiopia', 'latitude' => 8.0, 'longitude' => 38.0], + 'FI' => ['name' => 'Finland', 'latitude' => 64.0, 'longitude' => 26.0], + 'FJ' => ['name' => 'Fiji', 'latitude' => -18.0, 'longitude' => 175.0], + 'FR' => ['name' => 'France', 'latitude' => 46.0, 'longitude' => 2.0], + 'FM' => ['name' => 'Micronesia', 'latitude' => 6.92, 'longitude' => 158.25], + 'GA' => ['name' => 'Gabon', 'latitude' => -1.0, 'longitude' => 11.75], + 'GB' => ['name' => 'United Kingdom', 'latitude' => 54.0, 'longitude' => -2.0], + 'GE' => ['name' => 'Georgia', 'latitude' => 42.0, 'longitude' => 43.5], + 'GH' => ['name' => 'Ghana', 'latitude' => 8.0, 'longitude' => -2.0], + 'GN' => ['name' => 'Guinea', 'latitude' => 11.0, 'longitude' => -10.0], + 'GM' => ['name' => 'Gambia', 'latitude' => 13.47, 'longitude' => -16.57], + 'GW' => ['name' => 'Guinea-Bissau', 'latitude' => 12.0, 'longitude' => -15.0], + 'GQ' => ['name' => 'Equatorial Guinea', 'latitude' => 2.0, 'longitude' => 10.0], + 'GR' => ['name' => 'Greece', 'latitude' => 39.0, 'longitude' => 22.0], + 'GD' => ['name' => 'Grenada', 'latitude' => 12.12, 'longitude' => -61.67], + 'GT' => ['name' => 'Guatemala', 'latitude' => 15.5, 'longitude' => -90.25], + 'GY' => ['name' => 'Guyana', 'latitude' => 5.0, 'longitude' => -59.0], + 'HK' => ['name' => 'Hong Kong', 'latitude' => 22.25, 'longitude' => 114.17], + 'HN' => ['name' => 'Honduras', 'latitude' => 15.0, 'longitude' => -86.5], + 'HR' => ['name' => 'Croatia', 'latitude' => 45.17, 'longitude' => 15.5], + 'HT' => ['name' => 'Haiti', 'latitude' => 19.0, 'longitude' => -72.42], + 'HU' => ['name' => 'Hungary', 'latitude' => 47.0, 'longitude' => 20.0], + 'ID' => ['name' => 'Indonesia', 'latitude' => -5.0, 'longitude' => 120.0], + 'IN' => ['name' => 'India', 'latitude' => 20.0, 'longitude' => 77.0], + 'IE' => ['name' => 'Ireland', 'latitude' => 53.0, 'longitude' => -8.0], + 'IR' => ['name' => 'Iran', 'latitude' => 32.0, 'longitude' => 53.0], + 'IQ' => ['name' => 'Iraq', 'latitude' => 33.0, 'longitude' => 44.0], + 'IS' => ['name' => 'Iceland', 'latitude' => 65.0, 'longitude' => -18.0], + 'IL' => ['name' => 'Israel', 'latitude' => 31.5, 'longitude' => 34.75], + 'IT' => ['name' => 'Italy', 'latitude' => 42.83, 'longitude' => 12.83], + 'JM' => ['name' => 'Jamaica', 'latitude' => 18.25, 'longitude' => -77.5], + 'JO' => ['name' => 'Jordan', 'latitude' => 31.0, 'longitude' => 36.0], + 'JP' => ['name' => 'Japan', 'latitude' => 36.0, 'longitude' => 138.0], + 'KZ' => ['name' => 'Kazakhstan', 'latitude' => 48.0, 'longitude' => 68.0], + 'KE' => ['name' => 'Kenya', 'latitude' => 1.0, 'longitude' => 38.0], + 'KG' => ['name' => 'Kyrgyzstan', 'latitude' => 41.0, 'longitude' => 75.0], + 'KH' => ['name' => 'Cambodia', 'latitude' => 13.0, 'longitude' => 105.0], + 'KI' => ['name' => 'Kiribati', 'latitude' => 1.42, 'longitude' => 173.0], + 'KN' => ['name' => 'Saint Kitts and Nevis', 'latitude' => 17.33, 'longitude' => -62.75], + 'KR' => ['name' => 'South Korea', 'latitude' => 37.0, 'longitude' => 127.5], + 'KW' => ['name' => 'Kuwait', 'latitude' => 29.34, 'longitude' => 47.66], + 'LA' => ['name' => 'Laos', 'latitude' => 18.0, 'longitude' => 105.0], + 'LB' => ['name' => 'Lebanon', 'latitude' => 33.83, 'longitude' => 35.83], + 'LR' => ['name' => 'Liberia', 'latitude' => 6.5, 'longitude' => -9.5], + 'LY' => ['name' => 'Libya', 'latitude' => 25.0, 'longitude' => 17.0], + 'LC' => ['name' => 'Saint Lucia', 'latitude' => 13.88, 'longitude' => -61.13], + 'LI' => ['name' => 'Liechtenstein', 'latitude' => 47.17, 'longitude' => 9.53], + 'LK' => ['name' => 'Sri Lanka', 'latitude' => 7.0, 'longitude' => 81.0], + 'LS' => ['name' => 'Lesotho', 'latitude' => -29.5, 'longitude' => 28.5], + 'LT' => ['name' => 'Lithuania', 'latitude' => 56.0, 'longitude' => 24.0], + 'LU' => ['name' => 'Luxembourg', 'latitude' => 49.75, 'longitude' => 6.17], + 'LV' => ['name' => 'latitudevia', 'latitude' => 57.0, 'longitude' => 25.0], + 'MA' => ['name' => 'Morocco', 'latitude' => 32.0, 'longitude' => -5.0], + 'MC' => ['name' => 'Monaco', 'latitude' => 43.73, 'longitude' => 7.4], + 'MD' => ['name' => 'Moldova', 'latitude' => 47.0, 'longitude' => 29.0], + 'MG' => ['name' => 'Madagascar', 'latitude' => -20.0, 'longitude' => 47.0], + 'MV' => ['name' => 'Maldives', 'latitude' => 3.25, 'longitude' => 73.0], + 'MX' => ['name' => 'Mexico', 'latitude' => 23.0, 'longitude' => -102.0], + 'MH' => ['name' => 'Marshall Islands', 'latitude' => 9.0, 'longitude' => 168.0], + 'MK' => ['name' => 'North Macedonia', 'latitude' => 41.83, 'longitude' => 22.0], + 'ML' => ['name' => 'Mali', 'latitude' => 17.0, 'longitude' => -4.0], + 'MT' => ['name' => 'Malta', 'latitude' => 35.83, 'longitude' => 14.58], + 'MM' => ['name' => 'Myanmar', 'latitude' => 22.0, 'longitude' => 98.0], + 'ME' => ['name' => 'Montenegro', 'latitude' => 42.5, 'longitude' => 19.3], + 'MN' => ['name' => 'Mongolia', 'latitude' => 46.0, 'longitude' => 105.0], + 'MZ' => ['name' => 'Mozambique', 'latitude' => -18.25, 'longitude' => 35.0], + 'MR' => ['name' => 'Mauritania', 'latitude' => 20.0, 'longitude' => -12.0], + 'MU' => ['name' => 'Mauritius', 'latitude' => -20.28, 'longitude' => 57.55], + 'MW' => ['name' => 'Malawi', 'latitude' => -13.5, 'longitude' => 34.0], + 'MY' => ['name' => 'Malaysia', 'latitude' => 2.5, 'longitude' => 112.5], + 'NA' => ['name' => 'Namibia', 'latitude' => -22.0, 'longitude' => 17.0], + 'NE' => ['name' => 'Niger', 'latitude' => 16.0, 'longitude' => 8.0], + 'NG' => ['name' => 'Nigeria', 'latitude' => 10.0, 'longitude' => 8.0], + 'NI' => ['name' => 'Nicaragua', 'latitude' => 13.0, 'longitude' => -85.0], + 'NL' => ['name' => 'Netherlands', 'latitude' => 52.5, 'longitude' => 5.75], + 'NO' => ['name' => 'Norway', 'latitude' => 62.0, 'longitude' => 10.0], + 'NP' => ['name' => 'Nepal', 'latitude' => 28.0, 'longitude' => 84.0], + 'NR' => ['name' => 'Nauru', 'latitude' => -0.53, 'longitude' => 166.92], + 'NZ' => ['name' => 'New Zealand', 'latitude' => -41.0, 'longitude' => 174.0], + 'OM' => ['name' => 'Oman', 'latitude' => 21.0, 'longitude' => 57.0], + 'PK' => ['name' => 'Pakistan', 'latitude' => 30.0, 'longitude' => 70.0], + 'PS' => ['name' => 'Palestine', 'latitude' => 31.9, 'longitude' => 35.2], + 'PA' => ['name' => 'Panama', 'latitude' => 9.0, 'longitude' => -80.0], + 'PE' => ['name' => 'Peru', 'latitude' => -10.0, 'longitude' => -76.0], + 'PH' => ['name' => 'Philippines', 'latitude' => 13.0, 'longitude' => 122.0], + 'PW' => ['name' => 'Palau', 'latitude' => 7.5, 'longitude' => 134.5], + 'PG' => ['name' => 'Papua New Guinea', 'latitude' => -6.0, 'longitude' => 147.0], + 'PL' => ['name' => 'Poland', 'latitude' => 52.0, 'longitude' => 20.0], + 'KP' => ['name' => 'North Korea', 'latitude' => 40.0, 'longitude' => 127.0], + 'PT' => ['name' => 'Portugal', 'latitude' => 39.5, 'longitude' => -8.0], + 'PY' => ['name' => 'Paraguay', 'latitude' => -23.0, 'longitude' => -58.0], + 'QA' => ['name' => 'Qatar', 'latitude' => 25.5, 'longitude' => 51.25], + 'RO' => ['name' => 'Romania', 'latitude' => 46.0, 'longitude' => 25.0], + 'RU' => ['name' => 'Russia', 'latitude' => 60.0, 'longitude' => 100.0], + 'RW' => ['name' => 'Rwanda', 'latitude' => -2.0, 'longitude' => 30.0], + 'SA' => ['name' => 'Saudi Arabia', 'latitude' => 25.0, 'longitude' => 45.0], + 'SD' => ['name' => 'Sudan', 'latitude' => 15.0, 'longitude' => 30.0], + 'SN' => ['name' => 'Senegal', 'latitude' => 14.0, 'longitude' => -14.0], + 'SG' => ['name' => 'Singapore', 'latitude' => 1.37, 'longitude' => 103.8], + 'SB' => ['name' => 'Solomon Islands', 'latitude' => -8.0, 'longitude' => 159.0], + 'SL' => ['name' => 'Sierra Leone', 'latitude' => 8.5, 'longitude' => -11.5], + 'SV' => ['name' => 'El Salvador', 'latitude' => 13.83, 'longitude' => -88.92], + 'SM' => ['name' => 'San Marino', 'latitude' => 43.77, 'longitude' => 12.42], + 'SO' => ['name' => 'Somalia', 'latitude' => 10.0, 'longitude' => 49.0], + 'RS' => ['name' => 'Serbia', 'latitude' => 44.0, 'longitude' => 21.0], + 'SS' => ['name' => 'South Sudan', 'latitude' => 8.0, 'longitude' => 30.0], + 'ST' => ['name' => 'São Tomé and Príncipe', 'latitude' => 1.0, 'longitude' => 7.0], + 'SR' => ['name' => 'Suriname', 'latitude' => 4.0, 'longitude' => -56.0], + 'SK' => ['name' => 'Slovakia', 'latitude' => 48.67, 'longitude' => 19.5], + 'SI' => ['name' => 'Slovenia', 'latitude' => 46.0, 'longitude' => 15.0], + 'SE' => ['name' => 'Sweden', 'latitude' => 62.0, 'longitude' => 15.0], + 'SZ' => ['name' => 'Eswatini', 'latitude' => -26.5, 'longitude' => 31.5], + 'SC' => ['name' => 'Seychelles', 'latitude' => -4.58, 'longitude' => 55.67], + 'SY' => ['name' => 'Syria', 'latitude' => 35.0, 'longitude' => 38.0], + 'TD' => ['name' => 'Chad', 'latitude' => 15.0, 'longitude' => 19.0], + 'TG' => ['name' => 'Togo', 'latitude' => 8.0, 'longitude' => 1.17], + 'TH' => ['name' => 'Thailand', 'latitude' => 15.0, 'longitude' => 100.0], + 'TJ' => ['name' => 'Tajikistan', 'latitude' => 39.0, 'longitude' => 71.0], + 'TM' => ['name' => 'Turkmenistan', 'latitude' => 40.0, 'longitude' => 60.0], + 'TL' => ['name' => 'Timor-Leste', 'latitude' => -8.83, 'longitude' => 125.92], + 'TO' => ['name' => 'Tonga', 'latitude' => -20.0, 'longitude' => -175.0], + 'TT' => ['name' => 'Trinidad and Tobago', 'latitude' => 11.0, 'longitude' => -61.0], + 'TN' => ['name' => 'Tunisia', 'latitude' => 34.0, 'longitude' => 9.0], + 'TR' => ['name' => 'Turkey', 'latitude' => 39.0, 'longitude' => 35.0], + 'TV' => ['name' => 'Tuvalu', 'latitude' => -8.0, 'longitude' => 178.0], + 'TZ' => ['name' => 'Tanzania', 'latitude' => -6.0, 'longitude' => 35.0], + 'TW' => ['name' => 'Taiwan', 'latitude' => 23.5, 'longitude' => 121.0], + 'UG' => ['name' => 'Uganda', 'latitude' => 1.0, 'longitude' => 32.0], + 'UA' => ['name' => 'Ukraine', 'latitude' => 49.0, 'longitude' => 32.0], + 'UY' => ['name' => 'Uruguay', 'latitude' => -33.0, 'longitude' => -56.0], + 'US' => ['name' => 'United States', 'latitude' => 38.0, 'longitude' => -97.0], + 'UZ' => ['name' => 'Uzbekistan', 'latitude' => 41.0, 'longitude' => 64.0], + 'VA' => ['name' => 'Vatican City', 'latitude' => 41.9, 'longitude' => 12.45], + 'VC' => ['name' => 'Saint Vincent and the Grenadines', 'latitude' => 13.25, 'longitude' => -61.2], + 'VE' => ['name' => 'Venezuela', 'latitude' => 8.0, 'longitude' => -66.0], + 'VN' => ['name' => 'Vietnam', 'latitude' => 16.0, 'longitude' => 106.0], + 'VU' => ['name' => 'Vanuatu', 'latitude' => -16.0, 'longitude' => 167.0], + 'WS' => ['name' => 'Samoa', 'latitude' => -13.58, 'longitude' => -172.33], + 'YE' => ['name' => 'Yemen', 'latitude' => 15.0, 'longitude' => 48.0], + 'ZA' => ['name' => 'South Africa', 'latitude' => -29.0, 'longitude' => 24.0], + 'ZM' => ['name' => 'Zambia', 'latitude' => -15.0, 'longitude' => 30.0], + 'ZW' => ['name' => 'Zimbabwe', 'latitude' => -20.0, 'longitude' => 30.0], ]; diff --git a/app/config/platforms.php b/app/config/platforms.php index e54fb0a073..86f0a756c9 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -11,7 +11,7 @@ return [ [ 'key' => 'web', 'name' => 'Web', - 'version' => '16.0.2', + 'version' => '17.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' => '13.0.0', + 'version' => '15.0.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' => '7.0.0', + 'version' => '9.0.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' => '6.0.0', + 'version' => '6.1.0', '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.5.0', + 'version' => '0.7.1', 'url' => 'https://github.com/appwrite/sdk-for-react-native', 'package' => 'https://npmjs.com/package/react-native-appwrite', 'enabled' => true, @@ -217,7 +217,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '6.0.0', + 'version' => '6.2.2', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, @@ -245,7 +245,7 @@ return [ [ 'key' => 'nodejs', 'name' => 'Node.js', - 'version' => '14.1.0', + 'version' => '15.0.1', 'url' => 'https://github.com/appwrite/sdk-for-node', 'package' => 'https://www.npmjs.com/package/node-appwrite', 'enabled' => true, @@ -263,7 +263,7 @@ return [ [ 'key' => 'deno', 'name' => 'Deno', - 'version' => '12.1.0', + 'version' => '12.2.0', 'url' => 'https://github.com/appwrite/sdk-for-deno', 'package' => 'https://deno.land/x/appwrite', 'enabled' => true, @@ -281,7 +281,7 @@ return [ [ 'key' => 'php', 'name' => 'PHP', - 'version' => '12.1.0', + 'version' => '12.2.0', 'url' => 'https://github.com/appwrite/sdk-for-php', 'package' => 'https://packagist.org/packages/appwrite/appwrite', 'enabled' => true, @@ -299,7 +299,7 @@ return [ [ 'key' => 'python', 'name' => 'Python', - 'version' => '6.1.0', + 'version' => '9.0.2', 'url' => 'https://github.com/appwrite/sdk-for-python', 'package' => 'https://pypi.org/project/appwrite/', 'enabled' => true, @@ -317,7 +317,7 @@ return [ [ 'key' => 'ruby', 'name' => 'Ruby', - 'version' => '12.1.1', + 'version' => '12.2.0', 'url' => 'https://github.com/appwrite/sdk-for-ruby', 'package' => 'https://rubygems.org/gems/appwrite', 'enabled' => true, @@ -335,7 +335,7 @@ return [ [ 'key' => 'go', 'name' => 'Go', - 'version' => '0.2.0', + 'version' => '0.3.0', 'url' => 'https://github.com/appwrite/sdk-for-go', 'package' => 'https://github.com/appwrite/sdk-for-go', 'enabled' => true, @@ -353,7 +353,7 @@ return [ [ 'key' => 'dotnet', 'name' => '.NET', - 'version' => '0.10.1', + 'version' => '0.11.0', 'url' => 'https://github.com/appwrite/sdk-for-dotnet', 'package' => 'https://www.nuget.org/packages/Appwrite', 'enabled' => true, @@ -371,7 +371,7 @@ return [ [ 'key' => 'dart', 'name' => 'Dart', - 'version' => '12.1.0', + 'version' => '14.0.0', 'url' => 'https://github.com/appwrite/sdk-for-dart', 'package' => 'https://pub.dev/packages/dart_appwrite', 'enabled' => true, @@ -389,7 +389,7 @@ return [ [ 'key' => 'kotlin', 'name' => 'Kotlin', - 'version' => '6.1.0', + 'version' => '6.2.0', 'url' => 'https://github.com/appwrite/sdk-for-kotlin', 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-kotlin', 'enabled' => true, @@ -411,7 +411,7 @@ return [ [ 'key' => 'swift', 'name' => 'Swift', - 'version' => '6.1.0', + 'version' => '8.0.0', 'url' => 'https://github.com/appwrite/sdk-for-swift', 'package' => 'https://github.com/appwrite/sdk-for-swift', 'enabled' => true, diff --git a/app/config/regions.php b/app/config/regions.php index 61029a9996..05e04930fe 100644 --- a/app/config/regions.php +++ b/app/config/regions.php @@ -3,72 +3,8 @@ return [ 'default' => [ '$id' => 'default', - 'name' => 'Frankfurt', + 'name' => 'default', 'disabled' => false, - 'flag' => 'de', - 'default' => true, - ], - 'fra' => [ - '$id' => 'fra', - 'name' => 'Frankfurt', - 'disabled' => false, - 'flag' => 'de', - 'default' => true, - ], - 'nyc' => [ - '$id' => 'nyc', - 'name' => 'New York', - 'disabled' => true, - 'flag' => 'us', - 'default' => true, - ], - 'sfo' => [ - '$id' => 'sfo', - 'name' => 'San Francisco', - 'disabled' => true, - 'flag' => 'us', - 'default' => true, - ], - 'blr' => [ - '$id' => 'blr', - 'name' => 'Bengaluru', - 'disabled' => true, - 'flag' => 'in', - 'default' => true, - ], - 'lon' => [ - '$id' => 'lon', - 'name' => 'London', - 'disabled' => true, - 'flag' => 'gb', - 'default' => true, - ], - 'ams' => [ - '$id' => 'ams', - 'name' => 'Amsterdam', - 'disabled' => true, - 'flag' => 'nl', - 'default' => true, - ], - 'sgp' => [ - '$id' => 'sgp', - 'name' => 'Singapore', - 'disabled' => true, - 'flag' => 'sg', - 'default' => true, - ], - 'tor' => [ - '$id' => 'tor', - 'name' => 'Toronto', - 'disabled' => true, - 'flag' => 'ca', - 'default' => true, - ], - 'syd' => [ - '$id' => 'syd', - 'name' => 'Sydney', - 'disabled' => true, - 'flag' => 'au', 'default' => true, ], ]; diff --git a/app/config/roles.php b/app/config/roles.php index fae97895b8..a4abee0c45 100644 --- a/app/config/roles.php +++ b/app/config/roles.php @@ -26,6 +26,7 @@ $member = [ 'subscribers.write', 'subscribers.read', 'assistant.read', + 'rules.read' ]; $admins = [ @@ -58,6 +59,10 @@ $admins = [ 'health.read', 'functions.read', 'functions.write', + 'sites.read', + 'sites.write', + 'log.read', + 'log.write', 'execution.read', 'execution.write', 'rules.read', diff --git a/app/config/runtimes.php b/app/config/runtimes.php index 980613ebec..dbd33dac4b 100644 --- a/app/config/runtimes.php +++ b/app/config/runtimes.php @@ -6,4 +6,4 @@ use Appwrite\Runtimes\Runtimes; -return (new Runtimes('v4'))->getAll(); +return (new Runtimes('v5'))->getAll(); diff --git a/app/config/scopes.php b/app/config/scopes.php index 3765ab54fa..41fee82a81 100644 --- a/app/config/scopes.php +++ b/app/config/scopes.php @@ -64,6 +64,18 @@ return [ // List of publicly visible scopes 'functions.write' => [ 'description' => 'Access to create, update, and delete your project\'s functions and code deployments', ], + 'sites.read' => [ + 'description' => 'Access to read your project\'s sites and deployments', + ], + 'sites.write' => [ + 'description' => 'Access to create, update, and delete your project\'s sites and deployments', + ], + 'log.read' => [ + 'description' => 'Access to read your site\'s logs', + ], + 'log.write' => [ + 'description' => 'Access to update, and delete your site\'s logs', + ], 'execution.read' => [ 'description' => 'Access to read your project\'s execution logs', ], diff --git a/app/config/services.php b/app/config/services.php index c4fb98c59a..7e4656a277 100644 --- a/app/config/services.php +++ b/app/config/services.php @@ -173,12 +173,25 @@ return [ 'optional' => false, 'icon' => '', ], + 'sites' => [ + 'key' => 'sites', + 'name' => 'Sites', + 'subtitle' => 'The Sites Service allows you view, create and manage your web applications.', + 'description' => '/docs/services/sites.md', + 'controller' => '', // Uses modules + 'sdk' => true, + 'docs' => true, + 'docsUrl' => 'https://appwrite.io/docs/sites', + 'tests' => false, + 'optional' => true, + 'icon' => '/images/services/sites.png', + ], 'functions' => [ 'key' => 'functions', 'name' => 'Functions', 'subtitle' => 'The Functions Service allows you view, create and manage your Cloud Functions.', 'description' => '/docs/services/functions.md', - 'controller' => 'api/functions.php', + 'controller' => '', // Uses modules 'sdk' => true, 'docs' => true, 'docsUrl' => 'https://appwrite.io/docs/functions', diff --git a/app/config/runtimes/specifications.php b/app/config/specifications.php similarity index 90% rename from app/config/runtimes/specifications.php rename to app/config/specifications.php index 68880f4d4e..82f5633a96 100644 --- a/app/config/runtimes/specifications.php +++ b/app/config/specifications.php @@ -1,12 +1,12 @@ [ 'slug' => Specification::S_05VCPU_512MB, 'memory' => 512, - 'cpus' => 1 // TODO: revert this, it's a temporary change to test function performance. + 'cpus' => 0.5 ], Specification::S_1VCPU_512MB => [ 'slug' => Specification::S_1VCPU_512MB, diff --git a/app/config/specs/open-api3-1.6.x-client.json b/app/config/specs/open-api3-1.6.x-client.json index e3cd909b4e..316fe13116 100644 --- a/app/config/specs/open-api3-1.6.x-client.json +++ b/app/config/specs/open-api3-1.6.x-client.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "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", @@ -58,9 +58,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -109,9 +106,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -196,9 +190,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -274,9 +265,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -335,9 +323,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -400,9 +385,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -451,9 +433,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -519,9 +498,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -591,9 +567,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -659,9 +632,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -739,9 +709,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -809,9 +776,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -857,10 +821,10 @@ ], "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": { - "204": { - "description": "No content", + "200": { + "description": "Session", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/session" } @@ -885,9 +849,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -963,9 +924,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1016,9 +974,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1067,9 +1022,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1118,9 +1070,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1171,9 +1120,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1243,9 +1189,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1320,9 +1263,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1398,9 +1338,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1449,9 +1386,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1524,9 +1458,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1600,9 +1531,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1684,9 +1612,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1728,9 +1653,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1781,9 +1703,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1832,9 +1751,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1908,9 +1824,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1977,9 +1890,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2120,9 +2030,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2196,9 +2103,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2272,9 +2176,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2335,9 +2236,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2391,9 +2289,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2456,9 +2351,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2479,7 +2371,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2499,7 +2391,7 @@ "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2508,9 +2400,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2560,7 +2449,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2580,7 +2469,7 @@ "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2589,9 +2478,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2640,17 +2526,10 @@ "tags": [ "account" ], - "description": "", + "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", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/target" - } - } - } + "description": "No content" } }, "x-appwrite": { @@ -2660,7 +2539,7 @@ "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2669,9 +2548,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2733,9 +2609,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2784,7 +2657,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2817,9 +2690,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2896,9 +2766,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3042,9 +2909,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3118,9 +2982,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3188,9 +3049,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3269,9 +3127,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3320,9 +3175,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3392,9 +3244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3520,9 +3369,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3537,7 +3383,7 @@ "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.", + "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", @@ -3558,7 +3404,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3577,7 +3424,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ] }, "in": "path" @@ -3652,9 +3500,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3712,9 +3557,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4202,9 +4044,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4286,9 +4125,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4380,9 +4216,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4481,9 +4314,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4537,7 +4367,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -4568,9 +4398,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4677,9 +4504,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4774,9 +4598,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4875,9 +4696,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4961,9 +4779,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5049,9 +4864,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5166,9 +4978,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5242,9 +5051,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5296,9 +5102,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5350,9 +5153,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5404,9 +5204,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5458,9 +5255,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5512,9 +5306,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5566,9 +5357,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5620,9 +5408,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -5674,9 +5459,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5728,9 +5510,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5766,7 +5545,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -5783,9 +5562,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5851,7 +5627,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -5868,9 +5644,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5944,9 +5717,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6032,9 +5802,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6132,9 +5899,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6206,9 +5970,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6297,9 +6058,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6366,9 +6124,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6435,9 +6190,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6611,6 +6363,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -6653,9 +6406,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6729,9 +6479,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6807,9 +6554,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6894,9 +6638,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6958,9 +6699,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7034,9 +6772,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7100,9 +6835,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7188,9 +6920,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7301,9 +7030,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7375,9 +7101,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7464,9 +7187,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7539,9 +7259,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7639,9 +7356,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7702,9 +7416,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } diff --git a/app/config/specs/open-api3-1.6.x-console.json b/app/config/specs/open-api3-1.6.x-console.json index 369fea741a..54161c4262 100644 --- a/app/config/specs/open-api3-1.6.x-console.json +++ b/app/config/specs/open-api3-1.6.x-console.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "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", @@ -58,9 +58,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -108,9 +105,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -185,9 +179,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -236,9 +227,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -313,9 +301,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -373,9 +358,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -437,9 +419,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -488,9 +467,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -555,9 +531,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -626,9 +599,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -693,9 +663,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -772,9 +739,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -841,9 +805,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -889,10 +850,10 @@ ], "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": { - "204": { - "description": "No content", + "200": { + "description": "Session", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/session" } @@ -917,9 +878,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -994,9 +952,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1046,9 +1001,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1096,9 +1048,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1146,9 +1095,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1198,9 +1144,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1269,9 +1212,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1345,9 +1285,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1422,9 +1359,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1472,9 +1406,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1546,9 +1477,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1621,9 +1549,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1704,9 +1629,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1747,9 +1669,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1799,9 +1718,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1850,9 +1766,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1926,9 +1839,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1995,9 +1905,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2138,9 +2045,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2214,9 +2118,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2290,9 +2191,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2352,9 +2250,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2407,9 +2302,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2471,9 +2363,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2493,7 +2382,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2513,7 +2402,7 @@ "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2522,9 +2411,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2573,7 +2459,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2593,7 +2479,7 @@ "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2602,9 +2488,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2652,17 +2535,10 @@ "tags": [ "account" ], - "description": "", + "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", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/target" - } - } - } + "description": "No content" } }, "x-appwrite": { @@ -2672,7 +2548,7 @@ "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2681,9 +2557,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2744,9 +2617,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2795,7 +2665,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2828,9 +2698,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2907,9 +2774,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3053,9 +2917,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3129,9 +2990,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3198,9 +3056,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3278,9 +3133,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3328,9 +3180,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3399,9 +3248,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3527,9 +3373,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3544,7 +3387,7 @@ "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.", + "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", @@ -3565,7 +3408,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3584,7 +3428,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ] }, "in": "path" @@ -3659,9 +3504,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3719,9 +3561,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4209,9 +4048,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4293,9 +4129,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4387,9 +4220,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4457,7 +4287,7 @@ "tags": [ "assistant" ], - "description": "", + "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" @@ -4479,9 +4309,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4548,9 +4375,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4598,9 +4422,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4673,9 +4494,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4725,7 +4543,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -4745,7 +4563,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -4754,9 +4572,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4828,9 +4643,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4889,9 +4701,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4967,9 +4776,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5030,9 +4836,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5115,9 +4918,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5221,9 +5021,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5292,9 +5089,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5393,9 +5187,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5466,9 +5257,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5552,9 +5340,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5636,7 +5421,7 @@ "200": { "description": "AttributeBoolean", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeBoolean" } @@ -5660,9 +5445,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5773,9 +5555,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5857,7 +5636,7 @@ "200": { "description": "AttributeDatetime", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeDatetime" } @@ -5881,9 +5660,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5994,9 +5770,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6078,7 +5851,7 @@ "200": { "description": "AttributeEmail", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEmail" } @@ -6102,9 +5875,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6215,9 +5985,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6308,7 +6075,7 @@ "200": { "description": "AttributeEnum", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEnum" } @@ -6332,9 +6099,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6454,9 +6218,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6548,7 +6309,7 @@ "200": { "description": "AttributeFloat", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeFloat" } @@ -6572,9 +6333,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6651,8 +6409,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6697,9 +6453,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6791,7 +6544,7 @@ "200": { "description": "AttributeInteger", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeInteger" } @@ -6815,9 +6568,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6894,8 +6644,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6940,9 +6688,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7024,7 +6769,7 @@ "200": { "description": "AttributeIP", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeIp" } @@ -7048,9 +6793,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7161,9 +6903,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7294,9 +7033,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7389,7 +7125,7 @@ "200": { "description": "AttributeString", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeString" } @@ -7413,9 +7149,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7531,9 +7264,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7615,7 +7345,7 @@ "200": { "description": "AttributeURL", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeUrl" } @@ -7639,9 +7369,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7783,9 +7510,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7856,9 +7580,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7914,7 +7635,7 @@ "200": { "description": "AttributeRelationship", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeRelationship" } @@ -7938,9 +7659,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8050,9 +7768,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8106,7 +7821,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -8137,9 +7852,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8246,9 +7958,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8343,9 +8052,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8444,9 +8150,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8528,9 +8231,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8623,9 +8323,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8707,9 +8404,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8829,9 +8523,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8902,9 +8593,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8984,9 +8672,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9040,7 +8725,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -9060,7 +8745,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-collection-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -9069,9 +8754,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9163,9 +8845,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9209,7 +8888,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -9229,7 +8908,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-database-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -9238,9 +8917,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9322,9 +8998,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9397,9 +9070,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9488,7 +9158,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9645,9 +9316,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9697,9 +9365,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9748,9 +9413,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9850,9 +9512,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9883,7 +9542,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get usage metrics and statistics for a for all functions. View statistics including total functions, 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": "UsageFunctions", @@ -9903,7 +9562,7 @@ "type": "", "deprecated": false, "demo": "functions\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-functions-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -9912,9 +9571,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9986,9 +9642,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10047,9 +9700,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10145,7 +9795,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -10272,9 +9923,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10335,9 +9983,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10420,9 +10065,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10518,9 +10160,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10589,9 +10228,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10653,9 +10289,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10697,7 +10330,7 @@ "tags": [ "functions" ], - "description": "", + "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": { "204": { "description": "No content" @@ -10710,7 +10343,7 @@ "type": "", "deprecated": false, "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -10719,9 +10352,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10777,7 +10407,7 @@ "tags": [ "functions" ], - "description": "", + "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": "Build", @@ -10797,7 +10427,7 @@ "type": "", "deprecated": false, "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-deployment-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -10806,9 +10436,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10873,9 +10500,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10949,9 +10573,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11037,9 +10658,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11154,9 +10772,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11219,9 +10834,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11263,7 +10875,7 @@ "tags": [ "functions" ], - "description": "", + "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", @@ -11283,7 +10895,7 @@ "type": "", "deprecated": false, "demo": "functions\/get-function-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-function-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -11292,9 +10904,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11376,9 +10985,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11437,9 +11043,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11525,9 +11128,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11596,9 +11196,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11684,9 +11281,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11759,9 +11353,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11813,9 +11404,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11865,9 +11453,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11916,9 +11501,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11967,9 +11549,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12004,7 +11583,7 @@ }, "x-appwrite": { "method": "getCertificate", - "weight": 134, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -12018,9 +11597,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12080,9 +11656,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12117,7 +11690,7 @@ }, "x-appwrite": { "method": "getPubSub", - "weight": 130, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -12131,60 +11704,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [], - "Key": [] - } - ] - } - }, - "\/health\/queue": { - "get": { - "summary": "Get queue", - "operationId": "healthGetQueue", - "tags": [ - "health" - ], - "description": "Check the Appwrite queue messaging servers are up and connection is successful.", - "responses": { - "200": { - "description": "Health Status", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/healthStatus" - } - } - } - } - }, - "x-appwrite": { - "method": "getQueue", - "weight": 129, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "health\/get-queue.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "health.read", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12219,7 +11738,7 @@ }, "x-appwrite": { "method": "getQueueBuilds", - "weight": 136, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -12233,9 +11752,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12283,7 +11799,7 @@ }, "x-appwrite": { "method": "getQueueCertificates", - "weight": 135, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -12297,9 +11813,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12347,7 +11860,7 @@ }, "x-appwrite": { "method": "getQueueDatabases", - "weight": 137, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -12361,9 +11874,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12422,7 +11932,7 @@ }, "x-appwrite": { "method": "getQueueDeletes", - "weight": 138, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -12436,9 +11946,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12500,9 +12007,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12527,8 +12031,9 @@ "v1-audits", "v1-mails", "v1-functions", - "v1-usage", - "v1-usage-dump", + "v1-stats-resources", + "v1-stats-usage", + "v1-stats-usage-dump", "v1-webhooks", "v1-certificates", "v1-builds", @@ -12576,7 +12081,7 @@ }, "x-appwrite": { "method": "getQueueFunctions", - "weight": 142, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -12590,9 +12095,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12640,7 +12142,7 @@ }, "x-appwrite": { "method": "getQueueLogs", - "weight": 133, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -12654,9 +12156,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12704,7 +12203,7 @@ }, "x-appwrite": { "method": "getQueueMails", - "weight": 139, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -12718,9 +12217,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12768,7 +12264,7 @@ }, "x-appwrite": { "method": "getQueueMessaging", - "weight": 140, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -12782,9 +12278,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12832,7 +12325,7 @@ }, "x-appwrite": { "method": "getQueueMigrations", - "weight": 141, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -12846,9 +12339,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12874,9 +12364,70 @@ ] } }, - "\/health\/queue\/usage": { + "\/health\/queue\/stats-resources": { "get": { - "summary": "Get usage queue", + "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", + "weight": 142, + "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" @@ -12901,7 +12452,7 @@ "type": "", "deprecated": false, "demo": "health\/get-queue-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -12910,9 +12461,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12938,10 +12486,10 @@ ] } }, - "\/health\/queue\/usage-dump": { + "\/health\/queue\/stats-usage-dump": { "get": { "summary": "Get usage dump queue", - "operationId": "healthGetQueueUsageDump", + "operationId": "healthGetQueueStatsUsageDump", "tags": [ "health" ], @@ -12959,13 +12507,13 @@ } }, "x-appwrite": { - "method": "getQueueUsageDump", + "method": "getQueueStatsUsageDump", "weight": 144, "cookies": false, "type": "", "deprecated": false, - "demo": "health\/get-queue-usage-dump.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-usage-dump.md", + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -12974,9 +12522,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13024,7 +12569,7 @@ }, "x-appwrite": { "method": "getQueueWebhooks", - "weight": 132, + "weight": 131, "cookies": false, "type": "", "deprecated": false, @@ -13038,9 +12583,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13102,9 +12644,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13153,9 +12692,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13190,7 +12726,7 @@ }, "x-appwrite": { "method": "getTime", - "weight": 131, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -13204,9 +12740,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13257,9 +12790,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13311,9 +12841,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13365,9 +12892,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13419,9 +12943,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13473,9 +12994,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13527,9 +13045,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -13581,9 +13096,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13635,9 +13147,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13673,7 +13182,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -13688,9 +13197,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13751,7 +13257,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -13766,9 +13272,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13882,7 +13385,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -13897,7 +13400,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -13912,9 +13415,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14045,7 +13545,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -14060,9 +13560,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14120,7 +13617,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "x-example": "{}" }, "action": { @@ -14140,7 +13637,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "x-example": "" }, "color": { @@ -14154,9 +13651,9 @@ "x-example": "" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "x-example": "" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "x-example": null }, "draft": { "type": "boolean", @@ -14167,12 +13664,31 @@ "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", - "title", - "body" + "messageId" ] } } @@ -14187,7 +13703,7 @@ "tags": [ "messaging" ], - "description": "Update a push notification by its unique ID.\n", + "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", @@ -14202,7 +13718,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -14217,9 +13733,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14331,6 +13844,27 @@ "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": [] } } } @@ -14361,7 +13895,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -14376,9 +13910,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14457,7 +13988,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -14472,12 +14003,12 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.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}", @@ -14487,9 +14018,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14586,7 +14114,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -14601,9 +14129,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14641,7 +14166,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -14656,9 +14181,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14705,7 +14227,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -14720,9 +14242,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14782,7 +14301,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -14797,9 +14316,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14859,7 +14375,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -14874,9 +14390,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14937,7 +14450,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -14952,9 +14465,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15044,7 +14554,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -15059,9 +14569,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15154,7 +14661,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -15169,9 +14676,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15241,7 +14745,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -15256,9 +14760,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15331,7 +14832,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -15346,9 +14847,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15448,7 +14946,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -15463,9 +14961,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15568,7 +15063,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -15583,9 +15078,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15665,7 +15157,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -15680,9 +15172,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15765,7 +15254,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -15780,9 +15269,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15872,7 +15358,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -15887,9 +15373,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15982,7 +15465,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -15997,9 +15480,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16127,7 +15607,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -16142,9 +15622,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16274,7 +15751,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16289,9 +15766,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16371,7 +15845,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -16386,9 +15860,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16471,7 +15942,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16486,9 +15957,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16568,7 +16036,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -16583,9 +16051,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16668,7 +16133,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -16683,9 +16148,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16765,7 +16227,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -16780,9 +16242,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16865,7 +16324,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16880,9 +16339,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16962,7 +16418,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -16977,9 +16433,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17062,7 +16515,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -17077,9 +16530,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17117,7 +16567,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -17132,9 +16582,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17181,7 +16628,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -17196,9 +16643,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17258,7 +16702,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -17273,9 +16717,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17335,7 +16776,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -17350,9 +16791,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17411,7 +16849,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -17426,9 +16864,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17496,7 +16931,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -17511,9 +16946,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17558,7 +16990,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -17573,9 +17005,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17637,7 +17066,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -17652,9 +17081,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17701,7 +17127,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -17716,9 +17142,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17778,7 +17201,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -17793,9 +17216,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17864,7 +17284,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -17881,9 +17301,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17956,7 +17373,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -17971,9 +17388,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18021,7 +17435,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -18038,9 +17452,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18083,7 +17494,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18098,7 +17509,7 @@ }, "x-appwrite": { "method": "list", - "weight": 339, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -18112,9 +17523,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18159,7 +17567,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18188,9 +17596,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18216,17 +17621,17 @@ }, "endpoint": { "type": "string", - "description": "Source's Appwrite Endpoint", + "description": "Source Appwrite endpoint", "x-example": "https:\/\/example.com" }, "projectId": { "type": "string", - "description": "Source's Project ID", + "description": "Source Project ID", "x-example": "" }, "apiKey": { "type": "string", - "description": "Source's API Key", + "description": "Source API Key", "x-example": "" } }, @@ -18249,7 +17654,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18264,7 +17669,7 @@ }, "x-appwrite": { "method": "getAppwriteReport", - "weight": 341, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -18278,9 +17683,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18339,12 +17741,12 @@ }, "\/migrations\/firebase": { "post": { - "summary": "Migrate Firebase data (Service Account)", + "summary": "Migrate Firebase data", "operationId": "migrationsCreateFirebaseMigration", "tags": [ "migrations" ], - "description": "", + "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", @@ -18359,7 +17761,7 @@ }, "x-appwrite": { "method": "createFirebaseMigration", - "weight": 336, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -18373,9 +17775,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18415,177 +17814,6 @@ } } }, - "\/migrations\/firebase\/deauthorize": { - "get": { - "summary": "Revoke Appwrite's authorization to access Firebase projects", - "operationId": "migrationsDeleteFirebaseAuth", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "File" - } - }, - "x-appwrite": { - "method": "deleteFirebaseAuth", - "weight": 347, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/delete-firebase-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, - "\/migrations\/firebase\/oauth": { - "post": { - "summary": "Migrate Firebase data (OAuth)", - "operationId": "migrationsCreateFirebaseOAuthMigration", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "202": { - "description": "Migration", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/migration" - } - } - } - } - }, - "x-appwrite": { - "method": "createFirebaseOAuthMigration", - "weight": 335, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/create-firebase-o-auth-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, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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" - } - }, - "projectId": { - "type": "string", - "description": "Project ID of the Firebase Project", - "x-example": "" - } - }, - "required": [ - "resources", - "projectId" - ] - } - } - } - } - } - }, - "\/migrations\/firebase\/projects": { - "get": { - "summary": "List Firebase projects", - "operationId": "migrationsListFirebaseProjects", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migrations Firebase Projects List", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/firebaseProjectList" - } - } - } - } - }, - "x-appwrite": { - "method": "listFirebaseProjects", - "weight": 346, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/list-firebase-projects.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.read", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, "\/migrations\/firebase\/report": { "get": { "summary": "Generate a report on Firebase data", @@ -18593,7 +17821,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18608,7 +17836,7 @@ }, "x-appwrite": { "method": "getFirebaseReport", - "weight": 342, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -18622,9 +17850,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18660,80 +17885,6 @@ ] } }, - "\/migrations\/firebase\/report\/oauth": { - "get": { - "summary": "Generate a report on Firebase data using OAuth", - "operationId": "migrationsGetFirebaseReportOAuth", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migration Report", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/migrationReport" - } - } - } - } - }, - "x-appwrite": { - "method": "getFirebaseReportOAuth", - "weight": 343, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/get-firebase-report-o-auth.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, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ], - "parameters": [ - { - "name": "resources", - "description": "List of resources to migrate", - "required": true, - "schema": { - "type": "array", - "items": { - "type": "string" - } - }, - "in": "query" - }, - { - "name": "projectId", - "description": "Project ID", - "required": true, - "schema": { - "type": "string", - "x-example": "" - }, - "in": "query" - } - ] - } - }, "\/migrations\/nhost": { "post": { "summary": "Migrate NHost data", @@ -18741,7 +17892,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18756,7 +17907,7 @@ }, "x-appwrite": { "method": "createNHostMigration", - "weight": 338, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -18770,9 +17921,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18854,7 +18002,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18869,7 +18017,7 @@ }, "x-appwrite": { "method": "getNHostReport", - "weight": 349, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -18883,9 +18031,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18989,7 +18134,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19004,7 +18149,7 @@ }, "x-appwrite": { "method": "createSupabaseMigration", - "weight": 337, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -19018,9 +18163,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19096,7 +18238,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19111,7 +18253,7 @@ }, "x-appwrite": { "method": "getSupabaseReport", - "weight": 348, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -19125,9 +18267,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19222,7 +18361,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19237,7 +18376,7 @@ }, "x-appwrite": { "method": "get", - "weight": 340, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -19251,9 +18390,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19282,7 +18418,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Retry a failed migration. This endpoint allows you to retry a migration that has previously failed.", "responses": { "202": { "description": "Migration", @@ -19297,7 +18433,7 @@ }, "x-appwrite": { "method": "retry", - "weight": 350, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -19311,9 +18447,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19342,7 +18475,7 @@ "tags": [ "migrations" ], - "description": "", + "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" @@ -19350,7 +18483,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 351, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -19364,9 +18497,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19397,7 +18527,7 @@ "tags": [ "project" ], - "description": "", + "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", @@ -19417,7 +18547,7 @@ "type": "", "deprecated": false, "demo": "project\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -19426,9 +18556,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19516,9 +18643,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19564,9 +18688,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19639,9 +18760,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19699,9 +18817,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19776,9 +18891,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19809,7 +18921,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all projects. You can use the query params to filter your results. ", "responses": { "200": { "description": "Projects List", @@ -19829,7 +18941,7 @@ "type": "", "deprecated": false, "demo": "projects\/list.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -19838,9 +18950,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19883,7 +18992,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new project. You can create a maximum of 100 projects per account. ", "responses": { "201": { "description": "Project", @@ -19903,7 +19012,7 @@ "type": "", "deprecated": false, "demo": "projects\/create.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -19912,9 +19021,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20020,7 +19126,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20040,7 +19146,7 @@ "type": "", "deprecated": false, "demo": "projects\/get.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20049,9 +19155,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20080,7 +19183,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a project by its unique ID.", "responses": { "200": { "description": "Project", @@ -20100,7 +19203,7 @@ "type": "", "deprecated": false, "demo": "projects\/update.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20109,9 +19212,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20204,7 +19304,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a project by its unique ID.", "responses": { "204": { "description": "No content" @@ -20217,7 +19317,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20226,9 +19326,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20259,7 +19356,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20279,7 +19376,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-api-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20288,9 +19385,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20353,7 +19447,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20373,7 +19467,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-api-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20382,9 +19476,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20434,7 +19525,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update how long sessions created within a project should stay active for.", "responses": { "200": { "description": "Project", @@ -20454,7 +19545,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-duration.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20463,9 +19554,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20515,7 +19603,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the maximum number of users allowed in this project. Set to 0 for unlimited users. ", "responses": { "200": { "description": "Project", @@ -20535,7 +19623,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20544,9 +19632,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20596,7 +19681,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20616,7 +19701,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-sessions-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20625,9 +19710,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20677,7 +19759,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20697,7 +19779,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-memberships-privacy.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20706,9 +19788,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20770,7 +19849,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the list of mock phone numbers for testing. Use these numbers to bypass SMS verification in development. ", "responses": { "200": { "description": "Project", @@ -20790,7 +19869,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-mock-numbers.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20799,9 +19878,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20854,7 +19930,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20874,7 +19950,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-password-dictionary.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20883,9 +19959,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20935,7 +20008,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20955,7 +20028,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-password-history.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20964,9 +20037,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21016,7 +20086,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21036,7 +20106,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-personal-data-check.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21045,9 +20115,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21097,7 +20164,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Enable or disable session email alerts. When enabled, users will receive email notifications when new sessions are created.", "responses": { "200": { "description": "Project", @@ -21117,7 +20184,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-session-alerts.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21126,9 +20193,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21178,7 +20242,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21198,7 +20262,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21207,9 +20271,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21280,7 +20341,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new JWT token. This token can be used to authenticate users with custom scopes and expiration time. ", "responses": { "201": { "description": "JWT", @@ -21300,7 +20361,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-j-w-t.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21309,9 +20370,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21369,7 +20427,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all API keys from the current project. ", "responses": { "200": { "description": "API Keys List", @@ -21389,7 +20447,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-keys.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21398,9 +20456,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21429,7 +20484,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21449,7 +20504,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21458,9 +20513,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21524,7 +20576,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21544,7 +20596,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21553,9 +20605,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21594,7 +20643,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21614,7 +20663,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21623,9 +20672,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21697,7 +20743,7 @@ "tags": [ "projects" ], - "description": "", + "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" @@ -21710,7 +20756,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21719,9 +20765,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21762,7 +20805,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21782,7 +20825,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-o-auth2.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21791,9 +20834,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21901,7 +20941,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21921,7 +20961,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-platforms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21930,9 +20970,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21961,7 +20998,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21981,7 +21018,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21990,9 +21027,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22082,7 +21116,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22102,7 +21136,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22111,9 +21145,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22152,7 +21183,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22172,7 +21203,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22181,9 +21212,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22256,7 +21284,7 @@ "tags": [ "projects" ], - "description": "", + "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" @@ -22269,7 +21297,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22278,9 +21306,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22321,7 +21346,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of a specific service. Use this endpoint to enable or disable a service in your project. ", "responses": { "200": { "description": "Project", @@ -22341,7 +21366,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-service-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22350,9 +21375,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22423,7 +21445,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of all services. Use this endpoint to enable or disable all optional services at once. ", "responses": { "200": { "description": "Project", @@ -22443,7 +21465,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-service-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22452,9 +21474,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22504,7 +21523,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22524,7 +21543,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-smtp.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22533,9 +21552,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22631,7 +21647,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Send a test email to verify SMTP configuration. ", "responses": { "204": { "description": "No content" @@ -22644,7 +21660,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-smtp-test.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22653,9 +21669,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22757,7 +21770,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the team ID of a project allowing for it to be transferred to another team.", "responses": { "200": { "description": "Project", @@ -22777,7 +21790,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-team.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22786,9 +21799,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22838,7 +21848,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22858,7 +21868,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22867,9 +21877,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23064,14 +22071,14 @@ "tags": [ "projects" ], - "description": "", + "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": "Project", + "description": "EmailTemplate", "content": { "application\/json": { "schema": { - "$ref": "#\/components\/schemas\/project" + "$ref": "#\/components\/schemas\/emailTemplate" } } } @@ -23084,7 +22091,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23093,9 +22100,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23330,7 +22334,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -23350,7 +22354,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23359,9 +22363,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23558,7 +22559,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a custom SMS template for the specified locale and type returning it's contents.", "responses": { "200": { "description": "SmsTemplate", @@ -23578,7 +22579,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23587,9 +22588,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23781,7 +22779,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -23801,7 +22799,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23810,9 +22808,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24023,7 +23018,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24043,7 +23038,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24052,9 +23047,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24248,7 +23240,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24268,7 +23260,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-webhooks.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24277,9 +23269,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24308,7 +23297,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24328,7 +23317,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24337,9 +23326,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24425,7 +23411,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a webhook by its unique ID. This endpoint returns details about a specific webhook configured for a project. ", "responses": { "200": { "description": "Webhook", @@ -24445,7 +23431,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24454,9 +23440,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24495,7 +23478,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24515,7 +23498,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24524,9 +23507,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24620,7 +23600,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a webhook by its unique ID. Once deleted, the webhook will no longer receive project events. ", "responses": { "204": { "description": "No content" @@ -24633,7 +23613,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24642,9 +23622,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24685,7 +23662,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24705,7 +23682,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-webhook-signature.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24714,9 +23691,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24786,9 +23760,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24860,9 +23831,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24946,9 +23914,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24999,9 +23964,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25032,7 +23994,7 @@ "tags": [ "proxy" ], - "description": "", + "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", @@ -25052,7 +24014,7 @@ "type": "", "deprecated": false, "demo": "proxy\/update-rule-verification.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -25061,9 +24023,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25123,9 +24082,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25198,9 +24154,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25327,9 +24280,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25388,9 +24338,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25514,9 +24461,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25579,9 +24523,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25667,9 +24608,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25767,9 +24705,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25841,9 +24776,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25932,9 +24864,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26001,9 +24930,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26070,9 +24996,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26246,6 +25169,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -26288,9 +25212,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26333,7 +25254,7 @@ "tags": [ "storage" ], - "description": "", + "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", @@ -26353,7 +25274,7 @@ "type": "", "deprecated": false, "demo": "storage\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -26362,9 +25283,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26407,7 +25325,7 @@ "tags": [ "storage" ], - "description": "", + "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", @@ -26427,7 +25345,7 @@ "type": "", "deprecated": false, "demo": "storage\/get-bucket-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -26436,9 +25354,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26522,9 +25437,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26600,9 +25512,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26687,9 +25596,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26751,9 +25657,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26827,9 +25730,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26891,9 +25791,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26968,9 +25865,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27056,9 +25950,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27169,9 +26060,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27243,9 +26131,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27332,9 +26217,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27407,9 +26289,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27506,9 +26385,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27568,9 +26444,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27650,9 +26523,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27725,9 +26595,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27815,9 +26682,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27902,9 +26766,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27989,9 +26850,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28059,9 +26917,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28122,9 +26977,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28209,9 +27061,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28296,9 +27145,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28413,9 +27259,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28518,9 +27361,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28596,7 +27436,7 @@ "tags": [ "users" ], - "description": "", + "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", @@ -28616,7 +27456,7 @@ "type": "", "deprecated": false, "demo": "users\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -28625,9 +27465,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28699,9 +27536,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28753,9 +27587,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28816,9 +27647,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28898,9 +27726,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28982,9 +27807,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29067,9 +27889,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29143,9 +27962,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29206,9 +28022,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29261,15 +28074,8 @@ ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/user" - } - } - } + "204": { + "description": "No content" } }, "x-appwrite": { @@ -29288,9 +28094,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29366,9 +28169,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29429,9 +28229,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29490,9 +28287,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29551,9 +28345,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29614,9 +28405,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29696,9 +28484,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29778,9 +28563,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29860,9 +28642,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29921,9 +28700,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30003,9 +28779,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30064,9 +28837,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30118,9 +28888,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30174,9 +28941,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30247,9 +29011,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30330,9 +29091,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30405,9 +29163,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30517,9 +29272,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30589,9 +29341,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30680,9 +29429,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30753,9 +29499,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30837,9 +29580,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30919,9 +29659,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30972,7 +29709,7 @@ "tags": [ "vcs" ], - "description": "", + "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": "Provider Repositories List", @@ -30992,7 +29729,7 @@ "type": "", "deprecated": false, "demo": "vcs\/list-repositories.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31001,9 +29738,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31043,7 +29777,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31063,7 +29797,7 @@ "type": "", "deprecated": false, "demo": "vcs\/create-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31072,9 +29806,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31130,7 +29861,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31150,7 +29881,7 @@ "type": "", "deprecated": false, "demo": "vcs\/get-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31159,9 +29890,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31202,7 +29930,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31222,7 +29950,7 @@ "type": "", "deprecated": false, "demo": "vcs\/list-repository-branches.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31231,9 +29959,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31274,7 +29999,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31294,7 +30019,7 @@ "type": "", "deprecated": false, "demo": "vcs\/get-repository-contents.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31303,9 +30028,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31357,7 +30079,7 @@ "tags": [ "vcs" ], - "description": "", + "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": "Detection", @@ -31377,7 +30099,7 @@ "type": "", "deprecated": false, "demo": "vcs\/create-repository-detection.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31386,9 +30108,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31445,7 +30164,7 @@ "tags": [ "vcs" ], - "description": "", + "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" @@ -31458,7 +30177,7 @@ "type": "", "deprecated": false, "demo": "vcs\/update-external-deployments.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31467,9 +30186,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31529,7 +30245,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31558,9 +30274,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31605,7 +30318,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31634,9 +30347,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31665,7 +30375,7 @@ "tags": [ "vcs" ], - "description": "", + "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" @@ -31687,9 +30397,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -32749,30 +31456,6 @@ "migrations" ] }, - "firebaseProjectList": { - "description": "Migrations Firebase 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\/firebaseProject" - }, - "x-example": "" - } - }, - "required": [ - "total", - "projects" - ] - }, "specificationList": { "description": "Specifications List", "type": "object", @@ -35109,7 +33792,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { @@ -36976,7 +35659,8 @@ "resourceId": { "type": "string", "description": "Resource ID.", - "x-example": "5e5ea5c16897e" + "x-example": "5e5ea5c16897e", + "nullable": true }, "name": { "type": "string", @@ -36988,10 +35672,16 @@ "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": [ - "resourceId", "name", "value" ] @@ -37029,6 +35719,18 @@ "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.", @@ -37060,6 +35762,22 @@ "$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": [ @@ -37068,10 +35786,14 @@ "collectionsTotal", "documentsTotal", "storageTotal", + "databasesReadsTotal", + "databasesWritesTotal", "databases", "collections", "documents", - "storage" + "storage", + "databasesReads", + "databasesWrites" ] }, "usageDatabase": { @@ -37101,6 +35823,18 @@ "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.", @@ -37124,6 +35858,22 @@ "$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": [ @@ -37131,9 +35881,13 @@ "collectionsTotal", "documentsTotal", "storageTotal", + "databaseReadsTotal", + "databaseWritesTotal", "collections", "documents", - "storage" + "storage", + "databaseReads", + "databaseWrites" ] }, "usageCollection": { @@ -37310,6 +36064,20 @@ "$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": [ @@ -37317,7 +36085,9 @@ "filesTotal", "filesStorageTotal", "files", - "storage" + "storage", + "imageTransformations", + "imageTransformationsTotal" ] }, "usageFunctions": { @@ -37728,6 +36498,18 @@ "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.", @@ -37807,6 +36589,56 @@ "$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": [ @@ -37822,6 +36654,8 @@ "bucketsTotal", "executionsMbSecondsTotal", "buildsMbSecondsTotal", + "databasesReadsTotal", + "databasesWritesTotal", "requests", "network", "users", @@ -37831,7 +36665,14 @@ "databasesStorageBreakdown", "executionsMbSecondsBreakdown", "buildsMbSecondsBreakdown", - "functionsStorageBreakdown" + "functionsStorageBreakdown", + "authPhoneTotal", + "authPhoneEstimate", + "authPhoneCountryBreakdown", + "databasesReads", + "databasesWrites", + "imageTransformations", + "imageTransformationsTotal" ] }, "headers": { @@ -38707,26 +37548,6 @@ "size", "version" ] - }, - "firebaseProject": { - "description": "MigrationFirebaseProject", - "type": "object", - "properties": { - "projectId": { - "type": "string", - "description": "Project ID.", - "x-example": "my-project" - }, - "displayName": { - "type": "string", - "description": "Project display name.", - "x-example": "My Project" - } - }, - "required": [ - "projectId", - "displayName" - ] } }, "securitySchemes": { diff --git a/app/config/specs/open-api3-1.6.x-server.json b/app/config/specs/open-api3-1.6.x-server.json index e84b751743..3d32d3e978 100644 --- a/app/config/specs/open-api3-1.6.x-server.json +++ b/app/config/specs/open-api3-1.6.x-server.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "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", @@ -58,9 +58,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -110,9 +107,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -197,9 +191,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -276,9 +267,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -338,9 +326,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -404,9 +389,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -455,9 +437,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -524,9 +503,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -597,9 +573,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -666,9 +639,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -747,9 +717,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -818,9 +785,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -866,10 +830,10 @@ ], "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": { - "204": { - "description": "No content", + "200": { + "description": "Session", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/session" } @@ -894,9 +858,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -973,9 +934,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1027,9 +985,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1079,9 +1034,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1131,9 +1083,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1185,9 +1134,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1258,9 +1204,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1336,9 +1279,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1415,9 +1355,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1467,9 +1404,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1543,9 +1477,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1620,9 +1551,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1705,9 +1633,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1750,9 +1675,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1804,9 +1726,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1855,9 +1774,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1931,9 +1847,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2007,9 +1920,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2083,9 +1993,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2159,9 +2066,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2223,9 +2127,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2280,9 +2181,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2346,9 +2244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2400,9 +2295,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2451,7 +2343,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2484,9 +2376,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2563,9 +2452,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2709,9 +2595,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2785,9 +2668,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2856,9 +2736,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2938,9 +2815,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2990,9 +2864,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3063,9 +2934,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3193,9 +3061,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3212,7 +3077,7 @@ "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.", + "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", @@ -3233,7 +3098,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3252,7 +3118,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ] }, "in": "path" @@ -3327,9 +3194,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3389,9 +3253,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3881,9 +3742,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3967,9 +3825,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4063,9 +3918,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4164,9 +4016,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4240,9 +4089,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4322,9 +4168,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4384,9 +4227,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4463,9 +4303,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4527,9 +4364,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4613,9 +4447,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4720,9 +4551,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4792,9 +4620,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4894,9 +4719,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4968,9 +4790,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5055,9 +4874,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5140,7 +4956,7 @@ "200": { "description": "AttributeBoolean", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeBoolean" } @@ -5164,9 +4980,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5278,9 +5091,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5363,7 +5173,7 @@ "200": { "description": "AttributeDatetime", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeDatetime" } @@ -5387,9 +5197,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5501,9 +5308,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5586,7 +5390,7 @@ "200": { "description": "AttributeEmail", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEmail" } @@ -5610,9 +5414,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5724,9 +5525,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5818,7 +5616,7 @@ "200": { "description": "AttributeEnum", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEnum" } @@ -5842,9 +5640,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5965,9 +5760,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6060,7 +5852,7 @@ "200": { "description": "AttributeFloat", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeFloat" } @@ -6084,9 +5876,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6164,8 +5953,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6210,9 +5997,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6305,7 +6089,7 @@ "200": { "description": "AttributeInteger", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeInteger" } @@ -6329,9 +6113,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6409,8 +6190,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6455,9 +6234,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6540,7 +6316,7 @@ "200": { "description": "AttributeIP", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeIp" } @@ -6564,9 +6340,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6678,9 +6451,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6812,9 +6582,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6908,7 +6675,7 @@ "200": { "description": "AttributeString", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeString" } @@ -6932,9 +6699,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7051,9 +6815,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7136,7 +6897,7 @@ "200": { "description": "AttributeURL", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeUrl" } @@ -7160,9 +6921,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7305,9 +7063,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7379,9 +7134,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7438,7 +7190,7 @@ "200": { "description": "AttributeRelationship", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeRelationship" } @@ -7462,9 +7214,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7575,9 +7324,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7633,7 +7379,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -7664,9 +7410,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7775,9 +7518,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7874,9 +7614,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7977,9 +7714,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8063,9 +7797,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8148,9 +7879,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8271,9 +7999,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8345,9 +8070,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8428,9 +8150,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8504,9 +8223,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8596,7 +8312,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -8753,9 +8470,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8806,9 +8520,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8858,9 +8569,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8920,9 +8628,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9019,7 +8724,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9146,9 +8852,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9210,9 +8913,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9296,9 +8996,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9395,9 +9092,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9467,9 +9161,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9532,9 +9223,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9577,7 +9265,7 @@ "tags": [ "functions" ], - "description": "", + "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": { "204": { "description": "No content" @@ -9590,7 +9278,7 @@ "type": "", "deprecated": false, "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -9599,9 +9287,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9658,7 +9343,7 @@ "tags": [ "functions" ], - "description": "", + "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": "Build", @@ -9678,7 +9363,7 @@ "type": "", "deprecated": false, "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-deployment-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -9687,9 +9372,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9755,9 +9437,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9832,9 +9511,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -9922,9 +9598,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10041,9 +9714,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10108,9 +9778,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10182,9 +9849,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10244,9 +9908,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10333,9 +9994,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10405,9 +10063,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10494,9 +10149,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10570,9 +10222,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10626,9 +10275,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10680,9 +10326,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10732,9 +10375,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10784,9 +10424,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10822,7 +10459,7 @@ }, "x-appwrite": { "method": "getCertificate", - "weight": 134, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -10836,9 +10473,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10899,9 +10533,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10937,7 +10568,7 @@ }, "x-appwrite": { "method": "getPubSub", - "weight": 130, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -10951,61 +10582,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [], - "Key": [] - } - }, - "security": [ - { - "Project": [], - "Key": [] - } - ] - } - }, - "\/health\/queue": { - "get": { - "summary": "Get queue", - "operationId": "healthGetQueue", - "tags": [ - "health" - ], - "description": "Check the Appwrite queue messaging servers are up and connection is successful.", - "responses": { - "200": { - "description": "Health Status", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/healthStatus" - } - } - } - } - }, - "x-appwrite": { - "method": "getQueue", - "weight": 129, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "health\/get-queue.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "health.read", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11041,7 +10617,7 @@ }, "x-appwrite": { "method": "getQueueBuilds", - "weight": 136, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -11055,9 +10631,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11106,7 +10679,7 @@ }, "x-appwrite": { "method": "getQueueCertificates", - "weight": 135, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -11120,9 +10693,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11171,7 +10741,7 @@ }, "x-appwrite": { "method": "getQueueDatabases", - "weight": 137, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -11185,9 +10755,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11247,7 +10814,7 @@ }, "x-appwrite": { "method": "getQueueDeletes", - "weight": 138, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -11261,9 +10828,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11326,9 +10890,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11354,8 +10915,9 @@ "v1-audits", "v1-mails", "v1-functions", - "v1-usage", - "v1-usage-dump", + "v1-stats-resources", + "v1-stats-usage", + "v1-stats-usage-dump", "v1-webhooks", "v1-certificates", "v1-builds", @@ -11403,7 +10965,7 @@ }, "x-appwrite": { "method": "getQueueFunctions", - "weight": 142, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -11417,9 +10979,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11468,7 +11027,7 @@ }, "x-appwrite": { "method": "getQueueLogs", - "weight": 133, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -11482,9 +11041,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11533,7 +11089,7 @@ }, "x-appwrite": { "method": "getQueueMails", - "weight": 139, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -11547,9 +11103,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11598,7 +11151,7 @@ }, "x-appwrite": { "method": "getQueueMessaging", - "weight": 140, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -11612,9 +11165,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11663,7 +11213,7 @@ }, "x-appwrite": { "method": "getQueueMigrations", - "weight": 141, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -11677,9 +11227,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11706,9 +11253,71 @@ ] } }, - "\/health\/queue\/usage": { + "\/health\/queue\/stats-resources": { "get": { - "summary": "Get usage queue", + "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", + "weight": 142, + "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" @@ -11733,7 +11342,7 @@ "type": "", "deprecated": false, "demo": "health\/get-queue-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11742,9 +11351,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11771,10 +11377,10 @@ ] } }, - "\/health\/queue\/usage-dump": { + "\/health\/queue\/stats-usage-dump": { "get": { "summary": "Get usage dump queue", - "operationId": "healthGetQueueUsageDump", + "operationId": "healthGetQueueStatsUsageDump", "tags": [ "health" ], @@ -11792,13 +11398,13 @@ } }, "x-appwrite": { - "method": "getQueueUsageDump", + "method": "getQueueStatsUsageDump", "weight": 144, "cookies": false, "type": "", "deprecated": false, - "demo": "health\/get-queue-usage-dump.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-usage-dump.md", + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -11807,9 +11413,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11858,7 +11461,7 @@ }, "x-appwrite": { "method": "getQueueWebhooks", - "weight": 132, + "weight": 131, "cookies": false, "type": "", "deprecated": false, @@ -11872,9 +11475,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11937,9 +11537,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11989,9 +11586,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12027,7 +11621,7 @@ }, "x-appwrite": { "method": "getTime", - "weight": 131, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -12041,9 +11635,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12095,9 +11686,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12151,9 +11739,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12207,9 +11792,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12263,9 +11845,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12319,9 +11898,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12375,9 +11951,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [], "Session": [] @@ -12431,9 +12004,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12487,9 +12057,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12527,7 +12094,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -12542,9 +12109,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12606,7 +12170,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -12621,9 +12185,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12738,7 +12299,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -12753,7 +12314,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -12768,9 +12329,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12902,7 +12460,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -12917,9 +12475,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12978,7 +12533,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "x-example": "{}" }, "action": { @@ -12998,7 +12553,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "x-example": "" }, "color": { @@ -13012,9 +12567,9 @@ "x-example": "" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "x-example": "" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "x-example": null }, "draft": { "type": "boolean", @@ -13025,12 +12580,31 @@ "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", - "title", - "body" + "messageId" ] } } @@ -13045,7 +12619,7 @@ "tags": [ "messaging" ], - "description": "Update a push notification by its unique ID.\n", + "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", @@ -13060,7 +12634,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -13075,9 +12649,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13190,6 +12761,27 @@ "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": [] } } } @@ -13220,7 +12812,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -13235,9 +12827,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13317,7 +12906,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -13332,12 +12921,12 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.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}", @@ -13347,9 +12936,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13447,7 +13033,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -13462,9 +13048,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13503,7 +13086,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -13518,9 +13101,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13568,7 +13148,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -13583,9 +13163,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13646,7 +13223,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -13661,9 +13238,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13724,7 +13298,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -13739,9 +13313,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13803,7 +13374,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -13818,9 +13389,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13911,7 +13479,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -13926,9 +13494,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14022,7 +13587,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -14037,9 +13602,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14110,7 +13672,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -14125,9 +13687,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14201,7 +13760,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -14216,9 +13775,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14319,7 +13875,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14334,9 +13890,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14440,7 +13993,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -14455,9 +14008,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14538,7 +14088,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14553,9 +14103,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14639,7 +14186,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -14654,9 +14201,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14747,7 +14291,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -14762,9 +14306,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14858,7 +14399,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -14873,9 +14414,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15004,7 +14542,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -15019,9 +14557,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15152,7 +14687,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -15167,9 +14702,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15250,7 +14782,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -15265,9 +14797,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15351,7 +14880,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -15366,9 +14895,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15449,7 +14975,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -15464,9 +14990,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15550,7 +15073,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -15565,9 +15088,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15648,7 +15168,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -15663,9 +15183,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15749,7 +15266,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -15764,9 +15281,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15847,7 +15361,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -15862,9 +15376,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15948,7 +15459,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -15963,9 +15474,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16004,7 +15512,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -16019,9 +15527,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16069,7 +15574,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -16084,9 +15589,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16147,7 +15649,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -16162,9 +15664,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16225,7 +15724,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -16240,9 +15739,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16302,7 +15798,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -16317,9 +15813,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16388,7 +15881,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -16403,9 +15896,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16451,7 +15941,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -16466,9 +15956,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16531,7 +16018,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -16546,9 +16033,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16596,7 +16080,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -16611,9 +16095,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16674,7 +16155,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -16689,9 +16170,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16761,7 +16239,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -16778,9 +16256,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -16855,7 +16330,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -16870,9 +16345,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16921,7 +16393,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -16938,9 +16410,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -17014,9 +16483,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17090,9 +16556,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17220,9 +16683,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17282,9 +16742,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17409,9 +16866,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17475,9 +16929,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17565,9 +17016,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17667,9 +17115,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17743,9 +17188,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17836,9 +17278,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17907,9 +17346,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17978,9 +17414,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18156,6 +17589,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -18198,9 +17632,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18276,9 +17707,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18356,9 +17784,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18445,9 +17870,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18511,9 +17933,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18589,9 +18008,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18657,9 +18073,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18747,9 +18160,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18862,9 +18272,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18938,9 +18345,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19029,9 +18433,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19106,9 +18507,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19207,9 +18605,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19271,9 +18666,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19355,9 +18747,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19431,9 +18820,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19522,9 +18908,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19610,9 +18993,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19698,9 +19078,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19769,9 +19146,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19833,9 +19207,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19921,9 +19292,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20009,9 +19377,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20127,9 +19492,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20233,9 +19595,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20341,9 +19700,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20396,9 +19752,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20460,9 +19813,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20543,9 +19893,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20628,9 +19975,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20714,9 +20058,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20791,9 +20132,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20855,9 +20193,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20911,15 +20246,8 @@ ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/user" - } - } - } + "204": { + "description": "No content" } }, "x-appwrite": { @@ -20938,9 +20266,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21017,9 +20342,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21081,9 +20403,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21143,9 +20462,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21205,9 +20521,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21269,9 +20582,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21352,9 +20662,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21435,9 +20742,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21518,9 +20822,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21580,9 +20881,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21663,9 +20961,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21725,9 +21020,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21780,9 +21072,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21837,9 +21126,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21911,9 +21197,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21995,9 +21278,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22071,9 +21351,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22184,9 +21461,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22257,9 +21531,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22349,9 +21620,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22423,9 +21691,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22508,9 +21773,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22591,9 +21853,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -25746,7 +25005,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/config/specs/open-api3-1.7.x-client.json b/app/config/specs/open-api3-1.7.x-client.json new file mode 100644 index 0000000000..b50c4ebf4c --- /dev/null +++ b/app/config/specs/open-api3-1.7.x-client.json @@ -0,0 +1,9612 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "1.7.0", + "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" + } + ], + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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": "Verify authenticator", + "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", + "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", + "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", + "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": "Create 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", + "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", + "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": "Get 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", + "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", + "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": "Regenerate MFA recovery codes", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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": "Create 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", + "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", + "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", + "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", + "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", + "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", + "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", + "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, 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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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}", + "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", + "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", + "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, 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", + "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", + "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", + "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": "Create 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", + "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", + "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", + "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", + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "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", + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "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", + "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", + "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", + "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.\n", + "responses": { + "201": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "createDocument", + "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, + "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" + } + } + }, + "required": [ + "documentId", + "data" + ] + } + } + } + } + } + }, + "\/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", + "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" + } + ] + }, + "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", + "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", + "weight": 114, + "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" + } + ] + } + }, + "\/functions\/{functionId}\/executions": { + "get": { + "summary": "List executions", + "operationId": "functionsListExecutions", + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Executions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/executionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "weight": 383, + "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": "", + "responses": { + "201": { + "description": "Execution", + "content": { + "multipart\/form-data": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "createExecution", + "weight": 381, + "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": "", + "responses": { + "200": { + "description": "Execution", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "getExecution", + "weight": 382, + "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", + "weight": 303, + "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", + "weight": 302, + "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", + "weight": 118, + "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", + "weight": 119, + "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", + "weight": 123, + "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", + "weight": 120, + "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", + "weight": 121, + "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", + "weight": 122, + "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", + "weight": 124, + "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", + "weight": 125, + "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", + "weight": 348, + "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", + "weight": 352, + "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", + "weight": 209, + "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", + "weight": 208, + "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", + "weight": 210, + "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", + "weight": 215, + "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", + "weight": 216, + "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", + "weight": 212, + "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" + } + ] + } + }, + "\/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", + "weight": 211, + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "gif", + "png", + "webp", + "heic", + "avif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "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", + "weight": 213, + "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" + } + ] + } + }, + "\/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", + "weight": 220, + "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", + "weight": 219, + "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", + "weight": 221, + "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", + "weight": 223, + "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", + "weight": 225, + "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", + "weight": 227, + "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", + "weight": 226, + "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", + "weight": 228, + "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", + "weight": 229, + "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", + "weight": 231, + "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", + "weight": 230, + "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", + "weight": 222, + "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", + "weight": 224, + "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.", + "x-globalAttributes": [] + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.", + "x-globalAttributes": [] + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents", + "x-globalAttributes": [ + "databaseId" + ] + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location.", + "x-globalAttributes": [] + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health.", + "x-globalAttributes": [] + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files.", + "x-globalAttributes": [] + }, + { + "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", + "x-globalAttributes": [] + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users.", + "x-globalAttributes": [] + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions.", + "x-globalAttributes": [] + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.", + "x-globalAttributes": [] + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.", + "x-globalAttributes": [] + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations.", + "x-globalAttributes": [] + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project.", + "x-globalAttributes": [] + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).", + "x-globalAttributes": [] + } + ], + "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" + }, + "$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", + "$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" + } + } + }, + "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.7.x-console.json b/app/config/specs/open-api3-1.7.x-console.json new file mode 100644 index 0000000000..019047436a --- /dev/null +++ b/app/config/specs/open-api3-1.7.x-console.json @@ -0,0 +1,41627 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "1.7.0", + "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" + } + ], + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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": "Verify authenticator", + "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", + "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", + "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", + "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": "Create 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", + "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", + "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": "Get 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", + "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", + "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": "Regenerate MFA recovery codes", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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": "Create 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", + "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", + "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", + "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", + "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", + "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", + "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", + "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, 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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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}", + "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", + "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", + "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, 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", + "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", + "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", + "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": "Create 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", + "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", + "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", + "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", + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "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", + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "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", + "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", + "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": "Ask 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", + "weight": 305, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "getResource", + "weight": 423, + "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", + "weight": 304, + "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", + "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", + "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", + "weight": 115, + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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.\n", + "responses": { + "201": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "createDocument", + "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, + "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" + } + } + }, + "required": [ + "documentId", + "data" + ] + } + } + } + } + } + }, + "\/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", + "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" + } + ] + }, + "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", + "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", + "weight": 114, + "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", + "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}\/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", + "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", + "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" + } + } + }, + "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", + "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", + "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", + "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", + "weight": 117, + "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", + "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", + "weight": 116, + "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": "", + "responses": { + "200": { + "description": "Functions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/functionList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "weight": 367, + "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": "", + "responses": { + "201": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "weight": 364, + "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", + "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" + ], + "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": "", + "responses": { + "200": { + "description": "Runtimes List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/runtimeList" + } + } + } + } + }, + "x-appwrite": { + "method": "listRuntimes", + "weight": 369, + "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": "", + "responses": { + "200": { + "description": "Specifications List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/specificationList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "weight": 370, + "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": "", + "responses": { + "200": { + "description": "Function Templates List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/templateFunctionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTemplates", + "weight": 393, + "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": "", + "responses": { + "200": { + "description": "Template Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/templateFunction" + } + } + } + } + }, + "x-appwrite": { + "method": "getTemplate", + "weight": 392, + "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": "", + "responses": { + "200": { + "description": "UsageFunctions", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageFunctions" + } + } + } + } + }, + "x-appwrite": { + "method": "listUsage", + "weight": 386, + "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": "", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "weight": 365, + "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": "", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "weight": 366, + "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", + "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" + ], + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "weight": 368, + "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": "", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFunctionDeployment", + "weight": 373, + "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": "", + "responses": { + "200": { + "description": "Deployments List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deploymentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "weight": 374, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "weight": 371, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "weight": 379, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "weight": 376, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "weight": 377, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "weight": 372, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "weight": 375, + "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": "Download deployment", + "operationId": "functionsGetDeploymentDownload", + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "weight": 378, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "weight": 380, + "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": "", + "responses": { + "200": { + "description": "Executions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/executionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "weight": 383, + "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": "", + "responses": { + "201": { + "description": "Execution", + "content": { + "multipart\/form-data": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "createExecution", + "weight": 381, + "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": "", + "responses": { + "200": { + "description": "Execution", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "getExecution", + "weight": 382, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteExecution", + "weight": 384, + "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": "", + "responses": { + "200": { + "description": "UsageFunction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageFunction" + } + } + } + } + }, + "x-appwrite": { + "method": "getUsage", + "weight": 385, + "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": "", + "responses": { + "200": { + "description": "Variables List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variableList" + } + } + } + } + }, + "x-appwrite": { + "method": "listVariables", + "weight": 389, + "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": "", + "responses": { + "201": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "createVariable", + "weight": 387, + "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": "", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "getVariable", + "weight": 388, + "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": "", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "weight": 390, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "weight": 391, + "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", + "weight": 303, + "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", + "weight": 302, + "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", + "weight": 126, + "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", + "weight": 148, + "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", + "weight": 129, + "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", + "weight": 134, + "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", + "weight": 128, + "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", + "weight": 130, + "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", + "weight": 136, + "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", + "weight": 135, + "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", + "weight": 137, + "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", + "weight": 138, + "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", + "weight": 149, + "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-stats-usage-dump", + "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", + "weight": 142, + "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", + "weight": 133, + "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", + "weight": 139, + "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", + "weight": 140, + "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", + "weight": 141, + "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", + "weight": 143, + "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", + "weight": 144, + "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\/stats-usage-dump": { + "get": { + "summary": "Get usage dump queue", + "operationId": "healthGetQueueStatsUsageDump", + "tags": [ + "health" + ], + "description": "Get the number of projects containing 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": "getQueueStatsUsageDump", + "weight": 145, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.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", + "weight": 132, + "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", + "weight": 147, + "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", + "weight": 146, + "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", + "weight": 131, + "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", + "weight": 118, + "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", + "weight": 119, + "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", + "weight": 123, + "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", + "weight": 120, + "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", + "weight": 121, + "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", + "weight": 122, + "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", + "weight": 124, + "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", + "weight": 125, + "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", + "weight": 356, + "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", + "weight": 353, + "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", + "weight": 360, + "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", + "weight": 355, + "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", + "weight": 362, + "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", + "weight": 354, + "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", + "weight": 361, + "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", + "weight": 359, + "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", + "weight": 363, + "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", + "weight": 357, + "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", + "weight": 358, + "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", + "weight": 328, + "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", + "weight": 327, + "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", + "weight": 340, + "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", + "weight": 326, + "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", + "weight": 339, + "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", + "weight": 318, + "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", + "weight": 331, + "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", + "weight": 321, + "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", + "weight": 334, + "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", + "weight": 319, + "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", + "weight": 332, + "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", + "weight": 320, + "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", + "weight": 333, + "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", + "weight": 322, + "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", + "weight": 335, + "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", + "weight": 323, + "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", + "weight": 336, + "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", + "weight": 324, + "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", + "weight": 337, + "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", + "weight": 325, + "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", + "weight": 338, + "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", + "weight": 330, + "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", + "weight": 341, + "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", + "weight": 329, + "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", + "weight": 350, + "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", + "weight": 343, + "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", + "weight": 342, + "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", + "weight": 345, + "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", + "weight": 346, + "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", + "weight": 347, + "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", + "weight": 344, + "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", + "weight": 349, + "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", + "weight": 348, + "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", + "weight": 351, + "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", + "weight": 352, + "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", + "weight": 310, + "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": "Migrate Appwrite data", + "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", + "weight": 306, + "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": "Generate a report on Appwrite data", + "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", + "weight": 312, + "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\/firebase": { + "post": { + "summary": "Migrate Firebase data", + "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", + "weight": 307, + "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": "Generate a report on Firebase data", + "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", + "weight": 313, + "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": "Migrate NHost data", + "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", + "weight": 309, + "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": "Generate a report on NHost Data", + "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", + "weight": 315, + "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": "Migrate Supabase data", + "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", + "weight": 308, + "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": "Generate a report on Supabase Data", + "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", + "weight": 314, + "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", + "weight": 311, + "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": "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", + "weight": 316, + "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", + "weight": 317, + "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", + "weight": 197, + "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", + "weight": 199, + "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", + "weight": 198, + "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", + "weight": 200, + "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", + "weight": 201, + "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", + "weight": 202, + "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", + "weight": 152, + "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", + "weight": 151, + "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", + "weight": 153, + "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", + "weight": 154, + "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", + "weight": 171, + "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", + "weight": 158, + "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", + "weight": 159, + "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", + "weight": 164, + "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", + "weight": 163, + "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", + "weight": 169, + "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", + "weight": 162, + "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", + "weight": 170, + "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", + "weight": 167, + "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", + "weight": 166, + "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": "Enable or disable checking user passwords for similarity with their personal data.", + "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", + "weight": 168, + "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", + "weight": 161, + "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", + "weight": 165, + "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}\/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", + "weight": 183, + "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", + "weight": 179, + "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", + "weight": 178, + "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", + "weight": 180, + "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", + "weight": 181, + "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", + "weight": 182, + "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", + "weight": 160, + "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", + "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", + "weight": 185, + "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", + "weight": 184, + "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", + "weight": 186, + "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", + "weight": 187, + "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", + "weight": 188, + "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", + "weight": 156, + "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", + "weight": 157, + "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", + "weight": 189, + "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", + "weight": 190, + "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", + "weight": 155, + "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", + "weight": 192, + "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", + "weight": 194, + "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": "Reset 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", + "weight": 196, + "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", + "weight": 191, + "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", + "weight": 193, + "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", + "weight": 195, + "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", + "weight": 173, + "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", + "weight": 172, + "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", + "weight": 174, + "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", + "weight": 175, + "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", + "weight": 177, + "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", + "weight": 176, + "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", + "weight": 289, + "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": "", + "responses": { + "201": { + "description": "Rule", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRule" + } + } + } + } + }, + "x-appwrite": { + "method": "createAPIRule", + "weight": 424, + "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": "", + "responses": { + "201": { + "description": "Rule", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRule" + } + } + } + } + }, + "x-appwrite": { + "method": "createFunctionRule", + "weight": 426, + "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": "", + "responses": { + "201": { + "description": "Rule", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRule" + } + } + } + } + }, + "x-appwrite": { + "method": "createRedirectRule", + "weight": 427, + "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" + ] + } + }, + "required": [ + "domain", + "url", + "statusCode" + ] + } + } + } + } + } + }, + "\/proxy\/rules\/site": { + "post": { + "summary": "Create site rule", + "operationId": "proxyCreateSiteRule", + "tags": [ + "proxy" + ], + "description": "", + "responses": { + "201": { + "description": "Rule", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRule" + } + } + } + } + }, + "x-appwrite": { + "method": "createSiteRule", + "weight": 425, + "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", + "weight": 290, + "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", + "weight": 291, + "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", + "weight": 292, + "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": "", + "responses": { + "200": { + "description": "Sites List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/siteList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "weight": 396, + "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": "", + "responses": { + "201": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "weight": 394, + "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", + "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", + "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" + ], + "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": "", + "responses": { + "200": { + "description": "Frameworks List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/frameworkList" + } + } + } + } + }, + "x-appwrite": { + "method": "listFrameworks", + "weight": 399, + "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": "", + "responses": { + "200": { + "description": "Specifications List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/specificationList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "weight": 422, + "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": "", + "responses": { + "200": { + "description": "Site Templates List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/templateSiteList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTemplates", + "weight": 418, + "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": "", + "responses": { + "200": { + "description": "Template Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/templateSite" + } + } + } + } + }, + "x-appwrite": { + "method": "getTemplate", + "weight": 419, + "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": "", + "responses": { + "200": { + "description": "UsageSites", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageSites" + } + } + } + } + }, + "x-appwrite": { + "method": "listUsage", + "weight": 420, + "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": "", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "weight": 395, + "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": "", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "weight": 397, + "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", + "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", + "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" + ], + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "weight": 398, + "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": "", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSiteDeployment", + "weight": 405, + "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": "", + "responses": { + "200": { + "description": "Deployments List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deploymentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "weight": 404, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "weight": 400, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "weight": 408, + "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 deployment", + "operationId": "sitesCreateTemplateDeployment", + "tags": [ + "sites" + ], + "description": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "weight": 401, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "weight": 402, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "weight": 403, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "weight": 406, + "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": "Download deployment", + "operationId": "sitesGetDeploymentDownload", + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "weight": 407, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "weight": 409, + "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": "", + "responses": { + "200": { + "description": "Executions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/executionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "weight": 411, + "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": "", + "responses": { + "200": { + "description": "Execution", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "getLog", + "weight": 410, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteLog", + "weight": 412, + "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": "", + "responses": { + "200": { + "description": "UsageSite", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageSite" + } + } + } + } + }, + "x-appwrite": { + "method": "getUsage", + "weight": 421, + "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": "", + "responses": { + "200": { + "description": "Variables List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variableList" + } + } + } + } + }, + "x-appwrite": { + "method": "listVariables", + "weight": 415, + "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": "", + "responses": { + "201": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "createVariable", + "weight": 413, + "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": "", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "getVariable", + "weight": 414, + "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": "", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "weight": 416, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "weight": 417, + "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", + "weight": 204, + "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", + "weight": 203, + "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", + "weight": 205, + "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", + "weight": 206, + "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", + "weight": 207, + "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", + "weight": 209, + "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", + "weight": 208, + "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", + "weight": 210, + "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", + "weight": 215, + "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", + "weight": 216, + "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", + "weight": 212, + "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" + } + ] + } + }, + "\/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", + "weight": 211, + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "gif", + "png", + "webp", + "heic", + "avif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "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", + "weight": 213, + "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" + } + ] + } + }, + "\/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", + "weight": 217, + "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", + "weight": 218, + "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", + "weight": 220, + "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", + "weight": 219, + "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", + "weight": 221, + "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", + "weight": 223, + "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", + "weight": 225, + "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", + "weight": 232, + "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", + "weight": 227, + "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", + "weight": 226, + "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", + "weight": 228, + "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", + "weight": 229, + "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", + "weight": 231, + "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", + "weight": 230, + "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", + "weight": 222, + "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", + "weight": 224, + "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" + ] + } + } + } + } + } + }, + "\/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", + "weight": 242, + "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", + "weight": 233, + "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", + "weight": 236, + "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", + "weight": 234, + "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", + "weight": 250, + "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", + "weight": 273, + "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", + "weight": 235, + "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", + "weight": 238, + "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", + "weight": 239, + "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", + "weight": 240, + "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", + "weight": 237, + "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", + "weight": 275, + "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", + "weight": 243, + "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", + "weight": 271, + "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", + "weight": 256, + "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", + "weight": 274, + "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", + "weight": 252, + "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", + "weight": 248, + "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", + "weight": 247, + "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", + "weight": 261, + "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", + "weight": 266, + "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", + "weight": 262, + "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", + "weight": 263, + "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": "Regenerate MFA recovery codes", + "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", + "weight": 265, + "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", + "weight": 264, + "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", + "weight": 254, + "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", + "weight": 255, + "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", + "weight": 257, + "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", + "weight": 244, + "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", + "weight": 259, + "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", + "weight": 246, + "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", + "weight": 267, + "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", + "weight": 270, + "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", + "weight": 269, + "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", + "weight": 251, + "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", + "weight": 249, + "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: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "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", + "weight": 241, + "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", + "weight": 245, + "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", + "weight": 260, + "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", + "weight": 272, + "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", + "weight": 268, + "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", + "weight": 258, + "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", + "weight": 253, + "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", + "weight": 279, + "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", + "weight": 280, + "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", + "weight": 281, + "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", + "weight": 282, + "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", + "weight": 283, + "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", + "weight": 278, + "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": "Authorize external deployment", + "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", + "weight": 288, + "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", + "weight": 285, + "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", + "weight": 286, + "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", + "weight": 287, + "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.", + "x-globalAttributes": [] + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.", + "x-globalAttributes": [] + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents", + "x-globalAttributes": [ + "databaseId" + ] + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location.", + "x-globalAttributes": [] + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health.", + "x-globalAttributes": [] + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files.", + "x-globalAttributes": [] + }, + { + "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", + "x-globalAttributes": [] + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users.", + "x-globalAttributes": [] + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions.", + "x-globalAttributes": [] + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.", + "x-globalAttributes": [] + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.", + "x-globalAttributes": [] + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations.", + "x-globalAttributes": [] + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project.", + "x-globalAttributes": [] + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).", + "x-globalAttributes": [] + } + ], + "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" + ] + }, + "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" + ] + }, + "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 + } + }, + "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": [] + }, + "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", + "$createdAt", + "$updatedAt" + ] + }, + "document": { + "description": "Document", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Document ID.", + "x-example": "5e5ea5c16897e" + }, + "$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", + "$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" + ] + }, + "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": {} + }, + "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", + "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" + ] + }, + "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": [] + }, + "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": [] + } + }, + "required": [ + "range", + "functionsTotal", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "functions", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds" + ] + }, + "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" + }, + "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" + }, + "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": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds" + ] + }, + "usageSites": { + "description": "UsageSites", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "sitesTotal": { + "type": "integer", + "description": "Total aggregated number of sites.", + "x-example": 0, + "format": "int32" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of sites deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of sites deployment storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of sites build.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of sites build storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of sites build compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of sites build mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "sites": { + "type": "array", + "description": "Aggregated number of sites per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": 0 + }, + "deployments": { + "type": "array", + "description": "Aggregated number of sites deployment per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of sites deployment storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "builds": { + "type": "array", + "description": "Aggregated number of sites build per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of sites build storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of sites build compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated sum of sites build mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "sitesTotal", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "sites", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds" + ] + }, + "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 site deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of site deployments storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of site builds.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of site builds storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of site builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of site builds mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "Aggregated number of site deployments per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of site deployments storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "builds": { + "type": "array", + "description": "Aggregated number of site builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of site builds storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of site builds compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated number of site builds mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds" + ] + }, + "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": { + "type": "string", + "description": "CNAME target for your Appwrite custom domains.", + "x-example": "appwrite.io" + }, + "_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", + "_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" + ] + }, + "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", + "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.7.x-server.json b/app/config/specs/open-api3-1.7.x-server.json new file mode 100644 index 0000000000..9903453e60 --- /dev/null +++ b/app/config/specs/open-api3-1.7.x-server.json @@ -0,0 +1,29170 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "1.7.0", + "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" + } + ], + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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": "Verify authenticator", + "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", + "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", + "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", + "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": "Create 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", + "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", + "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": "Get 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", + "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", + "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": "Regenerate MFA recovery codes", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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": "Create 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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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}", + "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", + "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", + "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, 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", + "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", + "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", + "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": "Create 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", + "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", + "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", + "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", + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "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", + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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.\n", + "responses": { + "201": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "createDocument", + "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, + "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" + } + } + }, + "required": [ + "documentId", + "data" + ] + } + } + } + } + } + }, + "\/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", + "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" + } + ] + }, + "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", + "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", + "weight": 114, + "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}\/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", + "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", + "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" + } + } + }, + "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", + "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", + "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": "", + "responses": { + "200": { + "description": "Functions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/functionList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "weight": 367, + "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": "", + "responses": { + "201": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "weight": 364, + "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", + "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" + ], + "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": "", + "responses": { + "200": { + "description": "Runtimes List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/runtimeList" + } + } + } + } + }, + "x-appwrite": { + "method": "listRuntimes", + "weight": 369, + "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": "", + "responses": { + "200": { + "description": "Specifications List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/specificationList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "weight": 370, + "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": "", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "weight": 365, + "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": "", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "weight": 366, + "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", + "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" + ], + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "weight": 368, + "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": "", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFunctionDeployment", + "weight": 373, + "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": "", + "responses": { + "200": { + "description": "Deployments List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deploymentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "weight": 374, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "weight": 371, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "weight": 379, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "weight": 376, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "weight": 377, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "weight": 372, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "weight": 375, + "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": "Download deployment", + "operationId": "functionsGetDeploymentDownload", + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "weight": 378, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "weight": 380, + "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": "", + "responses": { + "200": { + "description": "Executions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/executionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "weight": 383, + "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": "", + "responses": { + "201": { + "description": "Execution", + "content": { + "multipart\/form-data": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "createExecution", + "weight": 381, + "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": "", + "responses": { + "200": { + "description": "Execution", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "getExecution", + "weight": 382, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteExecution", + "weight": 384, + "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": "", + "responses": { + "200": { + "description": "Variables List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variableList" + } + } + } + } + }, + "x-appwrite": { + "method": "listVariables", + "weight": 389, + "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": "", + "responses": { + "201": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "createVariable", + "weight": 387, + "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": "", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "getVariable", + "weight": 388, + "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": "", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "weight": 390, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "weight": 391, + "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", + "weight": 303, + "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", + "weight": 302, + "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", + "weight": 126, + "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", + "weight": 148, + "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", + "weight": 129, + "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", + "weight": 134, + "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", + "weight": 128, + "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", + "weight": 130, + "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", + "weight": 136, + "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", + "weight": 135, + "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", + "weight": 137, + "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", + "weight": 138, + "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", + "weight": 149, + "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-stats-usage-dump", + "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", + "weight": 142, + "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", + "weight": 133, + "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", + "weight": 139, + "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", + "weight": 140, + "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", + "weight": 141, + "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", + "weight": 143, + "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", + "weight": 144, + "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\/stats-usage-dump": { + "get": { + "summary": "Get usage dump queue", + "operationId": "healthGetQueueStatsUsageDump", + "tags": [ + "health" + ], + "description": "Get the number of projects containing 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": "getQueueStatsUsageDump", + "weight": 145, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.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", + "weight": 132, + "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", + "weight": 147, + "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", + "weight": 146, + "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", + "weight": 131, + "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", + "weight": 118, + "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", + "weight": 119, + "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", + "weight": 123, + "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", + "weight": 120, + "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", + "weight": 121, + "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", + "weight": 122, + "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", + "weight": 124, + "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", + "weight": 125, + "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", + "weight": 356, + "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", + "weight": 353, + "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", + "weight": 360, + "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", + "weight": 355, + "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", + "weight": 362, + "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", + "weight": 354, + "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", + "weight": 361, + "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", + "weight": 359, + "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", + "weight": 363, + "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", + "weight": 357, + "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", + "weight": 358, + "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", + "weight": 328, + "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", + "weight": 327, + "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", + "weight": 340, + "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", + "weight": 326, + "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", + "weight": 339, + "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", + "weight": 318, + "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", + "weight": 331, + "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", + "weight": 321, + "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", + "weight": 334, + "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", + "weight": 319, + "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", + "weight": 332, + "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", + "weight": 320, + "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", + "weight": 333, + "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", + "weight": 322, + "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", + "weight": 335, + "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", + "weight": 323, + "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", + "weight": 336, + "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", + "weight": 324, + "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", + "weight": 337, + "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", + "weight": 325, + "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", + "weight": 338, + "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", + "weight": 330, + "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", + "weight": 341, + "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", + "weight": 329, + "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", + "weight": 350, + "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", + "weight": 343, + "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", + "weight": 342, + "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", + "weight": 345, + "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", + "weight": 346, + "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", + "weight": 347, + "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", + "weight": 344, + "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", + "weight": 349, + "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", + "weight": 348, + "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", + "weight": 351, + "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", + "weight": 352, + "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": "", + "responses": { + "200": { + "description": "Sites List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/siteList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "weight": 396, + "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": "", + "responses": { + "201": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "weight": 394, + "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", + "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", + "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" + ], + "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": "", + "responses": { + "200": { + "description": "Frameworks List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/frameworkList" + } + } + } + } + }, + "x-appwrite": { + "method": "listFrameworks", + "weight": 399, + "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": "", + "responses": { + "200": { + "description": "Specifications List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/specificationList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "weight": 422, + "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": "", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "weight": 395, + "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": "", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "weight": 397, + "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", + "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", + "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" + ], + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "weight": 398, + "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": "", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSiteDeployment", + "weight": 405, + "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": "", + "responses": { + "200": { + "description": "Deployments List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deploymentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "weight": 404, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "weight": 400, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "weight": 408, + "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 deployment", + "operationId": "sitesCreateTemplateDeployment", + "tags": [ + "sites" + ], + "description": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "weight": 401, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "weight": 402, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "weight": 403, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "weight": 406, + "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": "Download deployment", + "operationId": "sitesGetDeploymentDownload", + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "weight": 407, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "weight": 409, + "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": "", + "responses": { + "200": { + "description": "Executions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/executionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "weight": 411, + "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": "", + "responses": { + "200": { + "description": "Execution", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "getLog", + "weight": 410, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteLog", + "weight": 412, + "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": "", + "responses": { + "200": { + "description": "Variables List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variableList" + } + } + } + } + }, + "x-appwrite": { + "method": "listVariables", + "weight": 415, + "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": "", + "responses": { + "201": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "createVariable", + "weight": 413, + "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": "", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "getVariable", + "weight": 414, + "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": "", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "weight": 416, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "weight": 417, + "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", + "weight": 204, + "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", + "weight": 203, + "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", + "weight": 205, + "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", + "weight": 206, + "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", + "weight": 207, + "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", + "weight": 209, + "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", + "weight": 208, + "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", + "weight": 210, + "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", + "weight": 215, + "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", + "weight": 216, + "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", + "weight": 212, + "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" + } + ] + } + }, + "\/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", + "weight": 211, + "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 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "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", + "gif", + "png", + "webp", + "heic", + "avif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "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", + "weight": 213, + "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" + } + ] + } + }, + "\/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", + "weight": 220, + "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", + "weight": 219, + "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", + "weight": 221, + "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", + "weight": 223, + "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", + "weight": 225, + "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", + "weight": 227, + "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", + "weight": 226, + "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", + "weight": 228, + "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", + "weight": 229, + "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", + "weight": 231, + "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", + "weight": 230, + "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", + "weight": 222, + "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", + "weight": 224, + "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" + ] + } + } + } + } + } + }, + "\/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", + "weight": 242, + "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", + "weight": 233, + "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", + "weight": 236, + "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", + "weight": 234, + "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", + "weight": 250, + "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", + "weight": 273, + "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", + "weight": 235, + "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", + "weight": 238, + "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", + "weight": 239, + "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", + "weight": 240, + "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", + "weight": 237, + "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", + "weight": 243, + "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", + "weight": 271, + "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", + "weight": 256, + "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", + "weight": 274, + "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", + "weight": 252, + "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", + "weight": 248, + "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", + "weight": 247, + "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", + "weight": 261, + "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", + "weight": 266, + "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", + "weight": 262, + "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", + "weight": 263, + "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": "Regenerate MFA recovery codes", + "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", + "weight": 265, + "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", + "weight": 264, + "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", + "weight": 254, + "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", + "weight": 255, + "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", + "weight": 257, + "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", + "weight": 244, + "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", + "weight": 259, + "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", + "weight": 246, + "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", + "weight": 267, + "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", + "weight": 270, + "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", + "weight": 269, + "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", + "weight": 251, + "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", + "weight": 249, + "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: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "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", + "weight": 241, + "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", + "weight": 245, + "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", + "weight": 260, + "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", + "weight": 272, + "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", + "weight": 268, + "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", + "weight": 258, + "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", + "weight": 253, + "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.", + "x-globalAttributes": [] + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.", + "x-globalAttributes": [] + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents", + "x-globalAttributes": [ + "databaseId" + ] + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location.", + "x-globalAttributes": [] + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health.", + "x-globalAttributes": [] + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files.", + "x-globalAttributes": [] + }, + { + "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", + "x-globalAttributes": [] + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users.", + "x-globalAttributes": [] + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions.", + "x-globalAttributes": [] + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.", + "x-globalAttributes": [] + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.", + "x-globalAttributes": [] + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations.", + "x-globalAttributes": [] + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project.", + "x-globalAttributes": [] + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).", + "x-globalAttributes": [] + } + ], + "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" + ] + }, + "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 + } + }, + "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": [] + }, + "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", + "$createdAt", + "$updatedAt" + ] + }, + "document": { + "description": "Document", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Document ID.", + "x-example": "5e5ea5c16897e" + }, + "$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", + "$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" + ] + }, + "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 e3cd909b4e..6d50b1e06e 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.6.0", + "version": "1.7.0", "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", @@ -43,7 +43,7 @@ }, "x-appwrite": { "method": "get", - "weight": 9, + "weight": 10, "cookies": false, "type": "", "deprecated": false, @@ -58,9 +58,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -94,7 +91,7 @@ }, "x-appwrite": { "method": "create", - "weight": 8, + "weight": 9, "cookies": false, "type": "", "deprecated": false, @@ -109,9 +106,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -181,7 +175,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 34, + "weight": 35, "cookies": false, "type": "", "deprecated": false, @@ -196,9 +190,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -259,7 +250,7 @@ }, "x-appwrite": { "method": "listIdentities", - "weight": 57, + "weight": 58, "cookies": false, "type": "", "deprecated": false, @@ -274,9 +265,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -320,7 +308,7 @@ }, "x-appwrite": { "method": "deleteIdentity", - "weight": 58, + "weight": 59, "cookies": false, "type": "", "deprecated": false, @@ -335,9 +323,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -385,7 +370,7 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 29, + "weight": 30, "cookies": false, "type": "", "deprecated": false, @@ -400,9 +385,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -436,7 +418,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 31, + "weight": 32, "cookies": false, "type": "", "deprecated": false, @@ -451,9 +433,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -504,7 +483,7 @@ }, "x-appwrite": { "method": "updateMFA", - "weight": 44, + "weight": 45, "cookies": false, "type": "", "deprecated": false, @@ -519,9 +498,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -576,7 +552,7 @@ }, "x-appwrite": { "method": "createMfaAuthenticator", - "weight": 46, + "weight": 47, "cookies": false, "type": "", "deprecated": false, @@ -591,9 +567,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -644,7 +617,7 @@ }, "x-appwrite": { "method": "updateMfaAuthenticator", - "weight": 47, + "weight": 48, "cookies": false, "type": "", "deprecated": false, @@ -659,9 +632,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -724,7 +694,7 @@ }, "x-appwrite": { "method": "deleteMfaAuthenticator", - "weight": 51, + "weight": 52, "cookies": false, "type": "", "deprecated": false, @@ -739,9 +709,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -794,7 +761,7 @@ }, "x-appwrite": { "method": "createMfaChallenge", - "weight": 52, + "weight": 53, "cookies": false, "type": "", "deprecated": false, @@ -809,9 +776,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -857,10 +821,10 @@ ], "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": { - "204": { - "description": "No content", + "200": { + "description": "Session", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/session" } @@ -870,7 +834,7 @@ }, "x-appwrite": { "method": "updateMfaChallenge", - "weight": 53, + "weight": 54, "cookies": false, "type": "", "deprecated": false, @@ -885,9 +849,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -948,7 +909,7 @@ }, "x-appwrite": { "method": "listMfaFactors", - "weight": 45, + "weight": 46, "cookies": false, "type": "", "deprecated": false, @@ -963,9 +924,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1001,7 +959,7 @@ }, "x-appwrite": { "method": "getMfaRecoveryCodes", - "weight": 50, + "weight": 51, "cookies": false, "type": "", "deprecated": false, @@ -1016,9 +974,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1052,7 +1007,7 @@ }, "x-appwrite": { "method": "createMfaRecoveryCodes", - "weight": 48, + "weight": 49, "cookies": false, "type": "", "deprecated": false, @@ -1067,9 +1022,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1103,7 +1055,7 @@ }, "x-appwrite": { "method": "updateMfaRecoveryCodes", - "weight": 49, + "weight": 50, "cookies": false, "type": "", "deprecated": false, @@ -1118,9 +1070,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1156,7 +1105,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 32, + "weight": 33, "cookies": false, "type": "", "deprecated": false, @@ -1171,9 +1120,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1228,7 +1174,7 @@ }, "x-appwrite": { "method": "updatePassword", - "weight": 33, + "weight": 34, "cookies": false, "type": "", "deprecated": false, @@ -1243,9 +1189,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1305,7 +1248,7 @@ }, "x-appwrite": { "method": "updatePhone", - "weight": 35, + "weight": 36, "cookies": false, "type": "", "deprecated": false, @@ -1320,9 +1263,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1383,7 +1323,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 30, + "weight": 31, "cookies": false, "type": "", "deprecated": false, @@ -1398,9 +1338,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1434,7 +1371,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 36, + "weight": 37, "cookies": false, "type": "", "deprecated": false, @@ -1449,9 +1386,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1506,7 +1440,7 @@ }, "x-appwrite": { "method": "createRecovery", - "weight": 38, + "weight": 39, "cookies": false, "type": "", "deprecated": false, @@ -1524,9 +1458,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1585,7 +1516,7 @@ }, "x-appwrite": { "method": "updateRecovery", - "weight": 39, + "weight": 40, "cookies": false, "type": "", "deprecated": false, @@ -1600,9 +1531,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1669,7 +1597,7 @@ }, "x-appwrite": { "method": "listSessions", - "weight": 11, + "weight": 12, "cookies": false, "type": "", "deprecated": false, @@ -1684,9 +1612,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1713,7 +1638,7 @@ }, "x-appwrite": { "method": "deleteSessions", - "weight": 12, + "weight": 13, "cookies": false, "type": "", "deprecated": false, @@ -1728,9 +1653,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1766,7 +1688,7 @@ }, "x-appwrite": { "method": "createAnonymousSession", - "weight": 17, + "weight": 18, "cookies": false, "type": "", "deprecated": false, @@ -1781,9 +1703,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1817,7 +1736,7 @@ }, "x-appwrite": { "method": "createEmailPasswordSession", - "weight": 16, + "weight": 17, "cookies": false, "type": "", "deprecated": false, @@ -1832,9 +1751,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1893,7 +1809,7 @@ }, "x-appwrite": { "method": "updateMagicURLSession", - "weight": 26, + "weight": 27, "cookies": false, "type": "", "deprecated": true, @@ -1908,9 +1824,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1962,7 +1875,7 @@ }, "x-appwrite": { "method": "createOAuth2Session", - "weight": 19, + "weight": 20, "cookies": false, "type": "webAuth", "deprecated": false, @@ -1977,9 +1890,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2105,7 +2015,7 @@ }, "x-appwrite": { "method": "updatePhoneSession", - "weight": 27, + "weight": 28, "cookies": false, "type": "", "deprecated": true, @@ -2120,9 +2030,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2181,7 +2088,7 @@ }, "x-appwrite": { "method": "createSession", - "weight": 18, + "weight": 19, "cookies": false, "type": "", "deprecated": false, @@ -2196,9 +2103,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2257,7 +2161,7 @@ }, "x-appwrite": { "method": "getSession", - "weight": 13, + "weight": 14, "cookies": false, "type": "", "deprecated": false, @@ -2272,9 +2176,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2320,7 +2221,7 @@ }, "x-appwrite": { "method": "updateSession", - "weight": 15, + "weight": 16, "cookies": false, "type": "", "deprecated": false, @@ -2335,9 +2236,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2376,7 +2274,7 @@ }, "x-appwrite": { "method": "deleteSession", - "weight": 14, + "weight": 15, "cookies": false, "type": "", "deprecated": false, @@ -2391,9 +2289,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2441,7 +2336,7 @@ }, "x-appwrite": { "method": "updateStatus", - "weight": 37, + "weight": 38, "cookies": false, "type": "", "deprecated": false, @@ -2456,9 +2351,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2479,7 +2371,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2494,12 +2386,12 @@ }, "x-appwrite": { "method": "createPushTarget", - "weight": 54, + "weight": 55, "cookies": false, "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2508,9 +2400,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2560,7 +2449,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2575,12 +2464,12 @@ }, "x-appwrite": { "method": "updatePushTarget", - "weight": 55, + "weight": 56, "cookies": false, "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2589,9 +2478,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2640,27 +2526,20 @@ "tags": [ "account" ], - "description": "", + "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", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/target" - } - } - } + "description": "No content" } }, "x-appwrite": { "method": "deletePushTarget", - "weight": 56, + "weight": 57, "cookies": false, "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2669,9 +2548,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2718,7 +2594,7 @@ }, "x-appwrite": { "method": "createEmailToken", - "weight": 25, + "weight": 26, "cookies": false, "type": "", "deprecated": false, @@ -2733,9 +2609,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2784,7 +2657,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2799,7 +2672,7 @@ }, "x-appwrite": { "method": "createMagicURLToken", - "weight": 24, + "weight": 25, "cookies": false, "type": "", "deprecated": false, @@ -2817,9 +2690,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2881,7 +2751,7 @@ }, "x-appwrite": { "method": "createOAuth2Token", - "weight": 23, + "weight": 24, "cookies": false, "type": "webAuth", "deprecated": false, @@ -2896,9 +2766,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3024,7 +2891,7 @@ }, "x-appwrite": { "method": "createPhoneToken", - "weight": 28, + "weight": 29, "cookies": false, "type": "", "deprecated": false, @@ -3042,9 +2909,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3103,7 +2967,7 @@ }, "x-appwrite": { "method": "createVerification", - "weight": 40, + "weight": 41, "cookies": false, "type": "", "deprecated": false, @@ -3118,9 +2982,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3173,7 +3034,7 @@ }, "x-appwrite": { "method": "updateVerification", - "weight": 41, + "weight": 42, "cookies": false, "type": "", "deprecated": false, @@ -3188,9 +3049,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3251,7 +3109,7 @@ }, "x-appwrite": { "method": "createPhoneVerification", - "weight": 42, + "weight": 43, "cookies": false, "type": "", "deprecated": false, @@ -3269,9 +3127,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3305,7 +3160,7 @@ }, "x-appwrite": { "method": "updatePhoneVerification", - "weight": 43, + "weight": 44, "cookies": false, "type": "", "deprecated": false, @@ -3320,9 +3175,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3376,7 +3228,7 @@ }, "x-appwrite": { "method": "getBrowser", - "weight": 60, + "weight": 61, "cookies": false, "type": "location", "deprecated": false, @@ -3392,9 +3244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3504,7 +3353,7 @@ }, "x-appwrite": { "method": "getCreditCard", - "weight": 59, + "weight": 60, "cookies": false, "type": "location", "deprecated": false, @@ -3520,9 +3369,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3537,7 +3383,7 @@ "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.", + "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", @@ -3558,7 +3404,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3577,7 +3424,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ] }, "in": "path" @@ -3636,7 +3484,7 @@ }, "x-appwrite": { "method": "getFavicon", - "weight": 63, + "weight": 64, "cookies": false, "type": "location", "deprecated": false, @@ -3652,9 +3500,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3696,7 +3541,7 @@ }, "x-appwrite": { "method": "getFlag", - "weight": 61, + "weight": 62, "cookies": false, "type": "location", "deprecated": false, @@ -3712,9 +3557,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4186,7 +4028,7 @@ }, "x-appwrite": { "method": "getImage", - "weight": 62, + "weight": 63, "cookies": false, "type": "location", "deprecated": false, @@ -4202,9 +4044,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4270,7 +4109,7 @@ }, "x-appwrite": { "method": "getInitials", - "weight": 65, + "weight": 66, "cookies": false, "type": "location", "deprecated": false, @@ -4286,9 +4125,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4364,7 +4200,7 @@ }, "x-appwrite": { "method": "getQR", - "weight": 64, + "weight": 65, "cookies": false, "type": "location", "deprecated": false, @@ -4380,9 +4216,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4465,7 +4298,7 @@ }, "x-appwrite": { "method": "listDocuments", - "weight": 109, + "weight": 110, "cookies": false, "type": "", "deprecated": false, @@ -4481,9 +4314,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4537,7 +4367,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -4552,7 +4382,7 @@ }, "x-appwrite": { "method": "createDocument", - "weight": 108, + "weight": 109, "cookies": false, "type": "", "deprecated": false, @@ -4568,9 +4398,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4661,7 +4488,7 @@ }, "x-appwrite": { "method": "getDocument", - "weight": 110, + "weight": 111, "cookies": false, "type": "", "deprecated": false, @@ -4677,9 +4504,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4758,7 +4582,7 @@ }, "x-appwrite": { "method": "updateDocument", - "weight": 112, + "weight": 113, "cookies": false, "type": "", "deprecated": false, @@ -4774,9 +4598,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4859,7 +4680,7 @@ }, "x-appwrite": { "method": "deleteDocument", - "weight": 113, + "weight": 114, "cookies": false, "type": "", "deprecated": false, @@ -4875,9 +4696,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4945,12 +4763,12 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 306, + "weight": 384, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-executions.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -4961,9 +4779,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4998,17 +4813,6 @@ "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" } ] }, @@ -5033,12 +4837,12 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 305, + "weight": 382, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -5049,9 +4853,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5150,12 +4951,12 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 307, + "weight": 383, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -5166,9 +4967,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5226,7 +5024,7 @@ }, "x-appwrite": { "method": "query", - "weight": 331, + "weight": 303, "cookies": false, "type": "graphql", "deprecated": false, @@ -5242,9 +5040,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5280,7 +5075,7 @@ }, "x-appwrite": { "method": "mutation", - "weight": 330, + "weight": 302, "cookies": false, "type": "graphql", "deprecated": false, @@ -5296,9 +5091,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5334,7 +5126,7 @@ }, "x-appwrite": { "method": "get", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -5350,9 +5142,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5388,7 +5177,7 @@ }, "x-appwrite": { "method": "listCodes", - "weight": 118, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -5404,9 +5193,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5442,7 +5228,7 @@ }, "x-appwrite": { "method": "listContinents", - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -5458,9 +5244,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5496,7 +5279,7 @@ }, "x-appwrite": { "method": "listCountries", - "weight": 119, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -5512,9 +5295,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5550,7 +5330,7 @@ }, "x-appwrite": { "method": "listCountriesEU", - "weight": 120, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -5566,9 +5346,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5604,7 +5381,7 @@ }, "x-appwrite": { "method": "listCountriesPhones", - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -5620,9 +5397,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -5658,7 +5432,7 @@ }, "x-appwrite": { "method": "listCurrencies", - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -5674,9 +5448,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5712,7 +5483,7 @@ }, "x-appwrite": { "method": "listLanguages", - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -5728,9 +5499,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5766,7 +5534,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -5783,9 +5551,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5851,7 +5616,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -5868,9 +5633,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5928,7 +5690,7 @@ }, "x-appwrite": { "method": "listFiles", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -5944,9 +5706,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6016,7 +5775,7 @@ }, "x-appwrite": { "method": "createFile", - "weight": 207, + "weight": 208, "cookies": false, "type": "upload", "deprecated": false, @@ -6032,9 +5791,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6116,7 +5872,7 @@ }, "x-appwrite": { "method": "getFile", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -6132,9 +5888,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6190,7 +5943,7 @@ }, "x-appwrite": { "method": "updateFile", - "weight": 214, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -6206,9 +5959,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6281,7 +6031,7 @@ }, "x-appwrite": { "method": "deleteFile", - "weight": 215, + "weight": 216, "cookies": false, "type": "", "deprecated": false, @@ -6297,9 +6047,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6350,7 +6097,7 @@ }, "x-appwrite": { "method": "getFileDownload", - "weight": 211, + "weight": 212, "cookies": false, "type": "location", "deprecated": false, @@ -6366,9 +6113,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6419,7 +6163,7 @@ }, "x-appwrite": { "method": "getFilePreview", - "weight": 210, + "weight": 211, "cookies": false, "type": "location", "deprecated": false, @@ -6435,9 +6179,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6611,6 +6352,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -6637,7 +6379,7 @@ }, "x-appwrite": { "method": "getFileView", - "weight": 212, + "weight": 213, "cookies": false, "type": "location", "deprecated": false, @@ -6653,9 +6395,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6713,7 +6452,7 @@ }, "x-appwrite": { "method": "list", - "weight": 219, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -6729,9 +6468,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6791,7 +6527,7 @@ }, "x-appwrite": { "method": "create", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -6807,9 +6543,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6878,7 +6611,7 @@ }, "x-appwrite": { "method": "get", - "weight": 220, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -6894,9 +6627,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6942,7 +6672,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -6958,9 +6688,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7018,7 +6745,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -7034,9 +6761,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7084,7 +6808,7 @@ }, "x-appwrite": { "method": "listMemberships", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -7100,9 +6824,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7127,7 +6848,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: userId, teamId, invited, joined, confirm", + "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", @@ -7172,7 +6893,7 @@ }, "x-appwrite": { "method": "createMembership", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -7188,9 +6909,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7285,7 +7003,7 @@ }, "x-appwrite": { "method": "getMembership", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -7301,9 +7019,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7359,7 +7074,7 @@ }, "x-appwrite": { "method": "updateMembership", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -7375,9 +7090,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7448,7 +7160,7 @@ }, "x-appwrite": { "method": "deleteMembership", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -7464,9 +7176,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7524,7 +7233,7 @@ }, "x-appwrite": { "method": "updateMembershipStatus", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -7539,9 +7248,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7624,7 +7330,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -7639,9 +7345,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7687,7 +7390,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -7702,9 +7405,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7803,6 +7503,11 @@ "description": "The Users service allows you to manage your project users.", "x-globalAttributes": [] }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, { "name": "functions", "description": "The Functions Service allows you view, create and manage your Cloud Functions.", @@ -9432,7 +9137,7 @@ }, "duration": { "type": "number", - "description": "Function execution duration in seconds.", + "description": "Resource(function\/site) execution duration in seconds.", "x-example": 0.4, "format": "double" }, diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 4e97fecc30..a1f9e94f6c 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.6.0", + "version": "1.7.0", "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", @@ -43,7 +43,7 @@ }, "x-appwrite": { "method": "get", - "weight": 9, + "weight": 10, "cookies": false, "type": "", "deprecated": false, @@ -58,9 +58,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -93,7 +90,7 @@ }, "x-appwrite": { "method": "create", - "weight": 8, + "weight": 9, "cookies": false, "type": "", "deprecated": false, @@ -108,9 +105,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -171,7 +165,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 10, + "weight": 11, "cookies": false, "type": "", "deprecated": false, @@ -185,9 +179,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -221,7 +212,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 34, + "weight": 35, "cookies": false, "type": "", "deprecated": false, @@ -236,9 +227,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -298,7 +286,7 @@ }, "x-appwrite": { "method": "listIdentities", - "weight": 57, + "weight": 58, "cookies": false, "type": "", "deprecated": false, @@ -313,9 +301,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -358,7 +343,7 @@ }, "x-appwrite": { "method": "deleteIdentity", - "weight": 58, + "weight": 59, "cookies": false, "type": "", "deprecated": false, @@ -373,9 +358,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -422,7 +404,7 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 29, + "weight": 30, "cookies": false, "type": "", "deprecated": false, @@ -437,9 +419,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -473,7 +452,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 31, + "weight": 32, "cookies": false, "type": "", "deprecated": false, @@ -488,9 +467,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -540,7 +516,7 @@ }, "x-appwrite": { "method": "updateMFA", - "weight": 44, + "weight": 45, "cookies": false, "type": "", "deprecated": false, @@ -555,9 +531,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -611,7 +584,7 @@ }, "x-appwrite": { "method": "createMfaAuthenticator", - "weight": 46, + "weight": 47, "cookies": false, "type": "", "deprecated": false, @@ -626,9 +599,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -678,7 +648,7 @@ }, "x-appwrite": { "method": "updateMfaAuthenticator", - "weight": 47, + "weight": 48, "cookies": false, "type": "", "deprecated": false, @@ -693,9 +663,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -757,7 +724,7 @@ }, "x-appwrite": { "method": "deleteMfaAuthenticator", - "weight": 51, + "weight": 52, "cookies": false, "type": "", "deprecated": false, @@ -772,9 +739,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -826,7 +790,7 @@ }, "x-appwrite": { "method": "createMfaChallenge", - "weight": 52, + "weight": 53, "cookies": false, "type": "", "deprecated": false, @@ -841,9 +805,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -889,10 +850,10 @@ ], "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": { - "204": { - "description": "No content", + "200": { + "description": "Session", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/session" } @@ -902,7 +863,7 @@ }, "x-appwrite": { "method": "updateMfaChallenge", - "weight": 53, + "weight": 54, "cookies": false, "type": "", "deprecated": false, @@ -917,9 +878,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -979,7 +937,7 @@ }, "x-appwrite": { "method": "listMfaFactors", - "weight": 45, + "weight": 46, "cookies": false, "type": "", "deprecated": false, @@ -994,9 +952,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1031,7 +986,7 @@ }, "x-appwrite": { "method": "getMfaRecoveryCodes", - "weight": 50, + "weight": 51, "cookies": false, "type": "", "deprecated": false, @@ -1046,9 +1001,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1081,7 +1033,7 @@ }, "x-appwrite": { "method": "createMfaRecoveryCodes", - "weight": 48, + "weight": 49, "cookies": false, "type": "", "deprecated": false, @@ -1096,9 +1048,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1131,7 +1080,7 @@ }, "x-appwrite": { "method": "updateMfaRecoveryCodes", - "weight": 49, + "weight": 50, "cookies": false, "type": "", "deprecated": false, @@ -1146,9 +1095,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1183,7 +1129,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 32, + "weight": 33, "cookies": false, "type": "", "deprecated": false, @@ -1198,9 +1144,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1254,7 +1197,7 @@ }, "x-appwrite": { "method": "updatePassword", - "weight": 33, + "weight": 34, "cookies": false, "type": "", "deprecated": false, @@ -1269,9 +1212,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1330,7 +1270,7 @@ }, "x-appwrite": { "method": "updatePhone", - "weight": 35, + "weight": 36, "cookies": false, "type": "", "deprecated": false, @@ -1345,9 +1285,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1407,7 +1344,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 30, + "weight": 31, "cookies": false, "type": "", "deprecated": false, @@ -1422,9 +1359,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1457,7 +1391,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 36, + "weight": 37, "cookies": false, "type": "", "deprecated": false, @@ -1472,9 +1406,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1528,7 +1459,7 @@ }, "x-appwrite": { "method": "createRecovery", - "weight": 38, + "weight": 39, "cookies": false, "type": "", "deprecated": false, @@ -1546,9 +1477,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1606,7 +1534,7 @@ }, "x-appwrite": { "method": "updateRecovery", - "weight": 39, + "weight": 40, "cookies": false, "type": "", "deprecated": false, @@ -1621,9 +1549,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1689,7 +1614,7 @@ }, "x-appwrite": { "method": "listSessions", - "weight": 11, + "weight": 12, "cookies": false, "type": "", "deprecated": false, @@ -1704,9 +1629,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1732,7 +1654,7 @@ }, "x-appwrite": { "method": "deleteSessions", - "weight": 12, + "weight": 13, "cookies": false, "type": "", "deprecated": false, @@ -1747,9 +1669,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1784,7 +1703,7 @@ }, "x-appwrite": { "method": "createAnonymousSession", - "weight": 17, + "weight": 18, "cookies": false, "type": "", "deprecated": false, @@ -1799,9 +1718,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1835,7 +1751,7 @@ }, "x-appwrite": { "method": "createEmailPasswordSession", - "weight": 16, + "weight": 17, "cookies": false, "type": "", "deprecated": false, @@ -1850,9 +1766,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1911,7 +1824,7 @@ }, "x-appwrite": { "method": "updateMagicURLSession", - "weight": 26, + "weight": 27, "cookies": false, "type": "", "deprecated": true, @@ -1926,9 +1839,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1980,7 +1890,7 @@ }, "x-appwrite": { "method": "createOAuth2Session", - "weight": 19, + "weight": 20, "cookies": false, "type": "webAuth", "deprecated": false, @@ -1995,9 +1905,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2123,7 +2030,7 @@ }, "x-appwrite": { "method": "updatePhoneSession", - "weight": 27, + "weight": 28, "cookies": false, "type": "", "deprecated": true, @@ -2138,9 +2045,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2199,7 +2103,7 @@ }, "x-appwrite": { "method": "createSession", - "weight": 18, + "weight": 19, "cookies": false, "type": "", "deprecated": false, @@ -2214,9 +2118,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2275,7 +2176,7 @@ }, "x-appwrite": { "method": "getSession", - "weight": 13, + "weight": 14, "cookies": false, "type": "", "deprecated": false, @@ -2290,9 +2191,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2337,7 +2235,7 @@ }, "x-appwrite": { "method": "updateSession", - "weight": 15, + "weight": 16, "cookies": false, "type": "", "deprecated": false, @@ -2352,9 +2250,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2392,7 +2287,7 @@ }, "x-appwrite": { "method": "deleteSession", - "weight": 14, + "weight": 15, "cookies": false, "type": "", "deprecated": false, @@ -2407,9 +2302,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2456,7 +2348,7 @@ }, "x-appwrite": { "method": "updateStatus", - "weight": 37, + "weight": 38, "cookies": false, "type": "", "deprecated": false, @@ -2471,9 +2363,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2493,7 +2382,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2508,12 +2397,12 @@ }, "x-appwrite": { "method": "createPushTarget", - "weight": 54, + "weight": 55, "cookies": false, "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2522,9 +2411,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2573,7 +2459,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2588,12 +2474,12 @@ }, "x-appwrite": { "method": "updatePushTarget", - "weight": 55, + "weight": 56, "cookies": false, "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2602,9 +2488,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2652,27 +2535,20 @@ "tags": [ "account" ], - "description": "", + "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", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/target" - } - } - } + "description": "No content" } }, "x-appwrite": { "method": "deletePushTarget", - "weight": 56, + "weight": 57, "cookies": false, "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2681,9 +2557,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2729,7 +2602,7 @@ }, "x-appwrite": { "method": "createEmailToken", - "weight": 25, + "weight": 26, "cookies": false, "type": "", "deprecated": false, @@ -2744,9 +2617,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2795,7 +2665,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2810,7 +2680,7 @@ }, "x-appwrite": { "method": "createMagicURLToken", - "weight": 24, + "weight": 25, "cookies": false, "type": "", "deprecated": false, @@ -2828,9 +2698,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2892,7 +2759,7 @@ }, "x-appwrite": { "method": "createOAuth2Token", - "weight": 23, + "weight": 24, "cookies": false, "type": "webAuth", "deprecated": false, @@ -2907,9 +2774,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3035,7 +2899,7 @@ }, "x-appwrite": { "method": "createPhoneToken", - "weight": 28, + "weight": 29, "cookies": false, "type": "", "deprecated": false, @@ -3053,9 +2917,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3114,7 +2975,7 @@ }, "x-appwrite": { "method": "createVerification", - "weight": 40, + "weight": 41, "cookies": false, "type": "", "deprecated": false, @@ -3129,9 +2990,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3183,7 +3041,7 @@ }, "x-appwrite": { "method": "updateVerification", - "weight": 41, + "weight": 42, "cookies": false, "type": "", "deprecated": false, @@ -3198,9 +3056,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3260,7 +3115,7 @@ }, "x-appwrite": { "method": "createPhoneVerification", - "weight": 42, + "weight": 43, "cookies": false, "type": "", "deprecated": false, @@ -3278,9 +3133,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3313,7 +3165,7 @@ }, "x-appwrite": { "method": "updatePhoneVerification", - "weight": 43, + "weight": 44, "cookies": false, "type": "", "deprecated": false, @@ -3328,9 +3180,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3383,7 +3232,7 @@ }, "x-appwrite": { "method": "getBrowser", - "weight": 60, + "weight": 61, "cookies": false, "type": "location", "deprecated": false, @@ -3399,9 +3248,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3511,7 +3357,7 @@ }, "x-appwrite": { "method": "getCreditCard", - "weight": 59, + "weight": 60, "cookies": false, "type": "location", "deprecated": false, @@ -3527,9 +3373,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3544,7 +3387,7 @@ "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.", + "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", @@ -3565,7 +3408,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3584,7 +3428,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ] }, "in": "path" @@ -3643,7 +3488,7 @@ }, "x-appwrite": { "method": "getFavicon", - "weight": 63, + "weight": 64, "cookies": false, "type": "location", "deprecated": false, @@ -3659,9 +3504,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3703,7 +3545,7 @@ }, "x-appwrite": { "method": "getFlag", - "weight": 61, + "weight": 62, "cookies": false, "type": "location", "deprecated": false, @@ -3719,9 +3561,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4193,7 +4032,7 @@ }, "x-appwrite": { "method": "getImage", - "weight": 62, + "weight": 63, "cookies": false, "type": "location", "deprecated": false, @@ -4209,9 +4048,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4277,7 +4113,7 @@ }, "x-appwrite": { "method": "getInitials", - "weight": 65, + "weight": 66, "cookies": false, "type": "location", "deprecated": false, @@ -4293,9 +4129,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4371,7 +4204,7 @@ }, "x-appwrite": { "method": "getQR", - "weight": 64, + "weight": 65, "cookies": false, "type": "location", "deprecated": false, @@ -4387,9 +4220,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4457,7 +4287,7 @@ "tags": [ "assistant" ], - "description": "", + "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" @@ -4465,7 +4295,7 @@ }, "x-appwrite": { "method": "chat", - "weight": 333, + "weight": 305, "cookies": false, "type": "", "deprecated": false, @@ -4479,9 +4309,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4512,6 +4339,73 @@ } } }, + "\/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", + "weight": 424, + "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": "<VALUE>" + }, + "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", @@ -4534,7 +4428,7 @@ }, "x-appwrite": { "method": "variables", - "weight": 332, + "weight": 304, "cookies": false, "type": "", "deprecated": false, @@ -4548,9 +4442,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4584,7 +4475,7 @@ }, "x-appwrite": { "method": "list", - "weight": 70, + "weight": 71, "cookies": false, "type": "", "deprecated": false, @@ -4598,9 +4489,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4659,7 +4547,7 @@ }, "x-appwrite": { "method": "create", - "weight": 69, + "weight": 70, "cookies": false, "type": "", "deprecated": false, @@ -4673,9 +4561,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4725,7 +4610,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -4740,12 +4625,12 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 114, + "weight": 115, "cookies": false, "type": "", "deprecated": false, "demo": "databases\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -4754,9 +4639,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4814,7 +4696,7 @@ }, "x-appwrite": { "method": "get", - "weight": 71, + "weight": 72, "cookies": false, "type": "", "deprecated": false, @@ -4828,9 +4710,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4875,7 +4754,7 @@ }, "x-appwrite": { "method": "update", - "weight": 73, + "weight": 74, "cookies": false, "type": "", "deprecated": false, @@ -4889,9 +4768,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4953,7 +4829,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 74, + "weight": 75, "cookies": false, "type": "", "deprecated": false, @@ -4967,9 +4843,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5016,7 +4889,7 @@ }, "x-appwrite": { "method": "listCollections", - "weight": 76, + "weight": 77, "cookies": false, "type": "", "deprecated": false, @@ -5030,9 +4903,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5101,7 +4971,7 @@ }, "x-appwrite": { "method": "createCollection", - "weight": 75, + "weight": 76, "cookies": false, "type": "", "deprecated": false, @@ -5115,9 +4985,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5207,7 +5074,7 @@ }, "x-appwrite": { "method": "getCollection", - "weight": 77, + "weight": 78, "cookies": false, "type": "", "deprecated": false, @@ -5221,9 +5088,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5278,7 +5142,7 @@ }, "x-appwrite": { "method": "updateCollection", - "weight": 79, + "weight": 80, "cookies": false, "type": "", "deprecated": false, @@ -5292,9 +5156,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5379,7 +5240,7 @@ }, "x-appwrite": { "method": "deleteCollection", - "weight": 80, + "weight": 81, "cookies": false, "type": "", "deprecated": false, @@ -5393,9 +5254,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5452,7 +5310,7 @@ }, "x-appwrite": { "method": "listAttributes", - "weight": 91, + "weight": 92, "cookies": false, "type": "", "deprecated": false, @@ -5466,9 +5324,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5538,7 +5393,7 @@ }, "x-appwrite": { "method": "createBooleanAttribute", - "weight": 88, + "weight": 89, "cookies": false, "type": "", "deprecated": false, @@ -5552,9 +5407,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5636,7 +5488,7 @@ "200": { "description": "AttributeBoolean", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeBoolean" } @@ -5646,7 +5498,7 @@ }, "x-appwrite": { "method": "updateBooleanAttribute", - "weight": 100, + "weight": 101, "cookies": false, "type": "", "deprecated": false, @@ -5660,9 +5512,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5759,7 +5608,7 @@ }, "x-appwrite": { "method": "createDatetimeAttribute", - "weight": 89, + "weight": 90, "cookies": false, "type": "", "deprecated": false, @@ -5773,9 +5622,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5857,7 +5703,7 @@ "200": { "description": "AttributeDatetime", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeDatetime" } @@ -5867,7 +5713,7 @@ }, "x-appwrite": { "method": "updateDatetimeAttribute", - "weight": 101, + "weight": 102, "cookies": false, "type": "", "deprecated": false, @@ -5881,9 +5727,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5980,7 +5823,7 @@ }, "x-appwrite": { "method": "createEmailAttribute", - "weight": 82, + "weight": 83, "cookies": false, "type": "", "deprecated": false, @@ -5994,9 +5837,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6078,7 +5918,7 @@ "200": { "description": "AttributeEmail", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEmail" } @@ -6088,7 +5928,7 @@ }, "x-appwrite": { "method": "updateEmailAttribute", - "weight": 94, + "weight": 95, "cookies": false, "type": "", "deprecated": false, @@ -6102,9 +5942,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6201,7 +6038,7 @@ }, "x-appwrite": { "method": "createEnumAttribute", - "weight": 83, + "weight": 84, "cookies": false, "type": "", "deprecated": false, @@ -6215,9 +6052,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6308,7 +6142,7 @@ "200": { "description": "AttributeEnum", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEnum" } @@ -6318,7 +6152,7 @@ }, "x-appwrite": { "method": "updateEnumAttribute", - "weight": 95, + "weight": 96, "cookies": false, "type": "", "deprecated": false, @@ -6332,9 +6166,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6440,7 +6271,7 @@ }, "x-appwrite": { "method": "createFloatAttribute", - "weight": 87, + "weight": 88, "cookies": false, "type": "", "deprecated": false, @@ -6454,9 +6285,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6548,7 +6376,7 @@ "200": { "description": "AttributeFloat", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeFloat" } @@ -6558,7 +6386,7 @@ }, "x-appwrite": { "method": "updateFloatAttribute", - "weight": 99, + "weight": 100, "cookies": false, "type": "", "deprecated": false, @@ -6572,9 +6400,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6651,8 +6476,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6683,7 +6506,7 @@ }, "x-appwrite": { "method": "createIntegerAttribute", - "weight": 86, + "weight": 87, "cookies": false, "type": "", "deprecated": false, @@ -6697,9 +6520,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6791,7 +6611,7 @@ "200": { "description": "AttributeInteger", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeInteger" } @@ -6801,7 +6621,7 @@ }, "x-appwrite": { "method": "updateIntegerAttribute", - "weight": 98, + "weight": 99, "cookies": false, "type": "", "deprecated": false, @@ -6815,9 +6635,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6894,8 +6711,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6926,7 +6741,7 @@ }, "x-appwrite": { "method": "createIpAttribute", - "weight": 84, + "weight": 85, "cookies": false, "type": "", "deprecated": false, @@ -6940,9 +6755,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7024,7 +6836,7 @@ "200": { "description": "AttributeIP", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeIp" } @@ -7034,7 +6846,7 @@ }, "x-appwrite": { "method": "updateIpAttribute", - "weight": 96, + "weight": 97, "cookies": false, "type": "", "deprecated": false, @@ -7048,9 +6860,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7147,7 +6956,7 @@ }, "x-appwrite": { "method": "createRelationshipAttribute", - "weight": 90, + "weight": 91, "cookies": false, "type": "", "deprecated": false, @@ -7161,9 +6970,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7280,7 +7086,7 @@ }, "x-appwrite": { "method": "createStringAttribute", - "weight": 81, + "weight": 82, "cookies": false, "type": "", "deprecated": false, @@ -7294,9 +7100,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7389,7 +7192,7 @@ "200": { "description": "AttributeString", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeString" } @@ -7399,7 +7202,7 @@ }, "x-appwrite": { "method": "updateStringAttribute", - "weight": 93, + "weight": 94, "cookies": false, "type": "", "deprecated": false, @@ -7413,9 +7216,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7517,7 +7317,7 @@ }, "x-appwrite": { "method": "createUrlAttribute", - "weight": 85, + "weight": 86, "cookies": false, "type": "", "deprecated": false, @@ -7531,9 +7331,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7615,7 +7412,7 @@ "200": { "description": "AttributeURL", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeUrl" } @@ -7625,7 +7422,7 @@ }, "x-appwrite": { "method": "updateUrlAttribute", - "weight": 97, + "weight": 98, "cookies": false, "type": "", "deprecated": false, @@ -7639,9 +7436,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7769,7 +7563,7 @@ }, "x-appwrite": { "method": "getAttribute", - "weight": 92, + "weight": 93, "cookies": false, "type": "", "deprecated": false, @@ -7783,9 +7577,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7842,7 +7633,7 @@ }, "x-appwrite": { "method": "deleteAttribute", - "weight": 103, + "weight": 104, "cookies": false, "type": "", "deprecated": false, @@ -7856,9 +7647,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7914,7 +7702,7 @@ "200": { "description": "AttributeRelationship", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeRelationship" } @@ -7924,7 +7712,7 @@ }, "x-appwrite": { "method": "updateRelationshipAttribute", - "weight": 102, + "weight": 103, "cookies": false, "type": "", "deprecated": false, @@ -7938,9 +7726,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8034,7 +7819,7 @@ }, "x-appwrite": { "method": "listDocuments", - "weight": 109, + "weight": 110, "cookies": false, "type": "", "deprecated": false, @@ -8050,9 +7835,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8106,7 +7888,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -8121,7 +7903,7 @@ }, "x-appwrite": { "method": "createDocument", - "weight": 108, + "weight": 109, "cookies": false, "type": "", "deprecated": false, @@ -8137,9 +7919,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8230,7 +8009,7 @@ }, "x-appwrite": { "method": "getDocument", - "weight": 110, + "weight": 111, "cookies": false, "type": "", "deprecated": false, @@ -8246,9 +8025,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8327,7 +8103,7 @@ }, "x-appwrite": { "method": "updateDocument", - "weight": 112, + "weight": 113, "cookies": false, "type": "", "deprecated": false, @@ -8343,9 +8119,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8428,7 +8201,7 @@ }, "x-appwrite": { "method": "deleteDocument", - "weight": 113, + "weight": 114, "cookies": false, "type": "", "deprecated": false, @@ -8444,9 +8217,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8514,7 +8284,7 @@ }, "x-appwrite": { "method": "listDocumentLogs", - "weight": 111, + "weight": 112, "cookies": false, "type": "", "deprecated": false, @@ -8528,9 +8298,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8609,7 +8376,7 @@ }, "x-appwrite": { "method": "listIndexes", - "weight": 105, + "weight": 106, "cookies": false, "type": "", "deprecated": false, @@ -8623,9 +8390,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8693,7 +8457,7 @@ }, "x-appwrite": { "method": "createIndex", - "weight": 104, + "weight": 105, "cookies": false, "type": "", "deprecated": false, @@ -8707,9 +8471,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8815,7 +8576,7 @@ }, "x-appwrite": { "method": "getIndex", - "weight": 106, + "weight": 107, "cookies": false, "type": "", "deprecated": false, @@ -8829,9 +8590,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8888,7 +8646,7 @@ }, "x-appwrite": { "method": "deleteIndex", - "weight": 107, + "weight": 108, "cookies": false, "type": "", "deprecated": false, @@ -8902,9 +8660,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8970,7 +8725,7 @@ }, "x-appwrite": { "method": "listCollectionLogs", - "weight": 78, + "weight": 79, "cookies": false, "type": "", "deprecated": false, @@ -8984,9 +8739,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9040,7 +8792,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -9055,12 +8807,12 @@ }, "x-appwrite": { "method": "getCollectionUsage", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, "demo": "databases\/get-collection-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -9069,9 +8821,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9149,7 +8898,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 72, + "weight": 73, "cookies": false, "type": "", "deprecated": false, @@ -9163,9 +8912,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9209,7 +8955,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -9224,12 +8970,12 @@ }, "x-appwrite": { "method": "getDatabaseUsage", - "weight": 115, + "weight": 116, "cookies": false, "type": "", "deprecated": false, "demo": "databases\/get-database-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -9238,9 +8984,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9308,12 +9051,12 @@ }, "x-appwrite": { "method": "list", - "weight": 289, + "weight": 368, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/list-functions.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}", @@ -9322,9 +9065,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9338,7 +9078,7 @@ "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, deployment, schedule, scheduleNext, schedulePrevious, timeout, entrypoint, commands, installationId", + "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", @@ -9383,12 +9123,12 @@ }, "x-appwrite": { "method": "create", - "weight": 288, + "weight": 365, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-function.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}", @@ -9397,9 +9137,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9452,6 +9189,7 @@ "python-3.11", "python-3.12", "python-ml-3.11", + "python-ml-3.12", "deno-1.21", "deno-1.24", "deno-1.35", @@ -9462,6 +9200,7 @@ "dart-2.16", "dart-2.17", "dart-2.18", + "dart-2.19", "dart-3.0", "dart-3.1", "dart-3.3", @@ -9488,7 +9227,10 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29" ], "x-enum-name": null, "x-enum-keys": [] @@ -9526,7 +9268,7 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "x-example": false }, "entrypoint": { @@ -9572,26 +9314,6 @@ "description": "Path to function code in the linked repo.", "x-example": "<PROVIDER_ROOT_DIRECTORY>" }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "x-example": "<TEMPLATE_REPOSITORY>" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "x-example": "<TEMPLATE_OWNER>" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "x-example": "<TEMPLATE_ROOT_DIRECTORY>" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "x-example": "<TEMPLATE_VERSION>" - }, "specification": { "type": "string", "description": "Runtime specification for the function and builds.", @@ -9631,23 +9353,20 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 290, + "weight": 370, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-runtimes.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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": "functions.read", + "scope": "public", "platforms": [ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9662,12 +9381,12 @@ }, "\/functions\/specifications": { "get": { - "summary": "List available function runtime specifications", + "summary": "List specifications", "operationId": "functionsListSpecifications", "tags": [ "functions" ], - "description": "List allowed function specifications for this instance.\n", + "description": "List allowed function specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -9682,12 +9401,12 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 291, + "weight": 371, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-specifications.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9697,9 +9416,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9714,7 +9430,7 @@ }, "\/functions\/templates": { "get": { - "summary": "List function templates", + "summary": "List templates", "operationId": "functionsListTemplates", "tags": [ "functions" @@ -9734,12 +9450,12 @@ }, "x-appwrite": { "method": "listTemplates", - "weight": 314, + "weight": 394, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-templates.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9748,9 +9464,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9836,12 +9549,12 @@ }, "x-appwrite": { "method": "getTemplate", - "weight": 315, + "weight": 393, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9850,9 +9563,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9879,11 +9589,11 @@ "\/functions\/usage": { "get": { "summary": "Get functions usage", - "operationId": "functionsGetUsage", + "operationId": "functionsListUsage", "tags": [ "functions" ], - "description": "", + "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", @@ -9897,13 +9607,13 @@ } }, "x-appwrite": { - "method": "getUsage", - "weight": 294, + "method": "listUsage", + "weight": 387, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -9912,9 +9622,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9972,12 +9679,12 @@ }, "x-appwrite": { "method": "get", - "weight": 292, + "weight": 366, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-function.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}", @@ -9986,9 +9693,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10033,12 +9737,12 @@ }, "x-appwrite": { "method": "update", - "weight": 295, + "weight": 367, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/update.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-function.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}", @@ -10047,9 +9751,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10109,6 +9810,7 @@ "python-3.11", "python-3.12", "python-ml-3.11", + "python-ml-3.12", "deno-1.21", "deno-1.24", "deno-1.35", @@ -10119,6 +9821,7 @@ "dart-2.16", "dart-2.17", "dart-2.18", + "dart-2.19", "dart-3.0", "dart-3.1", "dart-3.3", @@ -10145,7 +9848,10 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29" ], "x-enum-name": null, "x-enum-keys": [] @@ -10183,7 +9889,7 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "x-example": false }, "entrypoint": { @@ -10258,12 +9964,12 @@ }, "x-appwrite": { "method": "delete", - "weight": 298, + "weight": 369, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/delete-function.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}", @@ -10272,9 +9978,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10299,6 +10002,85 @@ ] } }, + "\/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", + "weight": 374, + "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": "<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", @@ -10306,7 +10088,7 @@ "tags": [ "functions" ], - "description": "Get a list of all the project's code deployments. You can use the query params to filter your results.", + "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", @@ -10321,12 +10103,12 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 300, + "weight": 375, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-deployments.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10335,9 +10117,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10361,7 +10140,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: size, buildId, activate, entrypoint, commands, type, size", + "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", @@ -10406,12 +10185,12 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 299, + "weight": 372, "cookies": false, "type": "upload", "deprecated": false, "demo": "functions\/create-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10420,9 +10199,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10482,16 +10258,16 @@ } } }, - "\/functions\/{functionId}\/deployments\/{deploymentId}": { - "get": { - "summary": "Get deployment", - "operationId": "functionsGetDeployment", + "\/functions\/{functionId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "functionsCreateDuplicateDeployment", "tags": [ "functions" ], - "description": "Get a code deployment by its unique ID.", + "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": { - "200": { + "202": { "description": "Deployment", "content": { "application\/json": { @@ -10503,24 +10279,21 @@ } }, "x-appwrite": { - "method": "getDeployment", - "weight": 301, + "method": "createDuplicateDeployment", + "weight": 380, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/get-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-deployment.md", + "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.read", + "scope": "functions.write", "platforms": [ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10541,46 +10314,62 @@ "x-example": "<FUNCTION_ID>" }, "in": "path" - }, - { - "name": "deploymentId", - "description": "Deployment ID.", - "required": true, - "schema": { - "type": "string", - "x-example": "<DEPLOYMENT_ID>" - }, - "in": "path" } - ] - }, - "patch": { - "summary": "Update deployment", - "operationId": "functionsUpdateDeployment", + ], + "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": "Update the function code deployment ID using the unique function ID. Use this endpoint to switch the code deployment that should be executed by the execution endpoint.", + "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": { - "200": { - "description": "Function", + "202": { + "description": "Deployment", "content": { "application\/json": { "schema": { - "$ref": "#\/components\/schemas\/function" + "$ref": "#\/components\/schemas\/deployment" } } } } }, "x-appwrite": { - "method": "updateDeployment", - "weight": 297, + "method": "createTemplateDeployment", + "weight": 377, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/update-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-function-deployment.md", + "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}", @@ -10589,9 +10378,204 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", + "auth": { + "Project": [] + } + }, + "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", + "weight": 378, + "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": "<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", + "weight": 373, + "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": [] } @@ -10639,12 +10623,12 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 302, + "weight": 376, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10653,162 +10637,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "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}\/build": { - "post": { - "summary": "Rebuild deployment", - "operationId": "functionsCreateBuild", - "tags": [ - "functions" - ], - "description": "", - "responses": { - "204": { - "description": "No content" - } - }, - "x-appwrite": { - "method": "createBuild", - "weight": 303, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "functions.write", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "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" - } - ], - "requestBody": { - "content": { - "application\/json": { - "schema": { - "type": "object", - "properties": { - "buildId": { - "type": "string", - "description": "Build unique ID.", - "x-example": "<BUILD_ID>" - } - } - } - } - } - } - }, - "patch": { - "summary": "Cancel deployment", - "operationId": "functionsUpdateDeploymentBuild", - "tags": [ - "functions" - ], - "description": "", - "responses": { - "200": { - "description": "Build", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/build" - } - } - } - } - }, - "x-appwrite": { - "method": "updateDeploymentBuild", - "weight": 304, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "functions.write", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10850,7 +10678,7 @@ "tags": [ "functions" ], - "description": "Get a Deployment's contents by its unique ID. This endpoint supports range requests for partial or streaming file download.", + "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" @@ -10858,12 +10686,12 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 296, + "weight": 379, "cookies": false, "type": "location", "deprecated": false, "demo": "functions\/get-deployment-download.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10873,9 +10701,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10887,6 +10712,93 @@ "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", + "weight": 381, + "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", @@ -10933,12 +10845,12 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 306, + "weight": 384, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-executions.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10949,9 +10861,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10986,17 +10895,6 @@ "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" } ] }, @@ -11021,12 +10919,12 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 305, + "weight": 382, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11037,9 +10935,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11138,12 +11033,12 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 307, + "weight": 383, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11154,9 +11049,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11197,7 +11089,7 @@ "tags": [ "functions" ], - "description": "Delete a function execution by its unique ID.\n", + "description": "Delete a function execution by its unique ID.", "responses": { "204": { "description": "No content" @@ -11205,12 +11097,12 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 308, + "weight": 385, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11219,9 +11111,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11259,11 +11148,11 @@ "\/functions\/{functionId}\/usage": { "get": { "summary": "Get function usage", - "operationId": "functionsGetFunctionUsage", + "operationId": "functionsGetUsage", "tags": [ "functions" ], - "description": "", + "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", @@ -11277,13 +11166,13 @@ } }, "x-appwrite": { - "method": "getFunctionUsage", - "weight": 293, + "method": "getUsage", + "weight": 386, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/get-function-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -11292,9 +11181,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11362,12 +11248,12 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 310, + "weight": 390, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-variables.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11376,9 +11262,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11423,12 +11306,12 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 309, + "weight": 388, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11437,9 +11320,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11477,6 +11357,11 @@ "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": [ @@ -11511,12 +11396,12 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 311, + "weight": 389, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11525,9 +11410,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11582,12 +11464,12 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 312, + "weight": 391, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/update-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11596,9 +11478,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11646,6 +11525,11 @@ "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": [ @@ -11670,12 +11554,12 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 313, + "weight": 392, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11684,9 +11568,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11743,7 +11624,7 @@ }, "x-appwrite": { "method": "query", - "weight": 331, + "weight": 303, "cookies": false, "type": "graphql", "deprecated": false, @@ -11759,9 +11640,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11797,7 +11675,7 @@ }, "x-appwrite": { "method": "mutation", - "weight": 330, + "weight": 302, "cookies": false, "type": "graphql", "deprecated": false, @@ -11813,9 +11691,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11851,7 +11726,7 @@ }, "x-appwrite": { "method": "get", - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -11865,9 +11740,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11902,7 +11774,7 @@ }, "x-appwrite": { "method": "getAntivirus", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -11916,9 +11788,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11953,7 +11822,7 @@ }, "x-appwrite": { "method": "getCache", - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -11967,9 +11836,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12018,9 +11884,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12066,7 +11929,7 @@ }, "x-appwrite": { "method": "getDB", - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -12080,9 +11943,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12131,60 +11991,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [], - "Key": [] - } - ] - } - }, - "\/health\/queue": { - "get": { - "summary": "Get queue", - "operationId": "healthGetQueue", - "tags": [ - "health" - ], - "description": "Check the Appwrite queue messaging servers are up and connection is successful.", - "responses": { - "200": { - "description": "Health Status", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/healthStatus" - } - } - } - } - }, - "x-appwrite": { - "method": "getQueue", - "weight": 129, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "health\/get-queue.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "health.read", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12233,9 +12039,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12297,9 +12100,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12361,9 +12161,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12436,9 +12233,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12486,7 +12280,7 @@ }, "x-appwrite": { "method": "getFailedJobs", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -12500,9 +12294,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12527,8 +12318,9 @@ "v1-audits", "v1-mails", "v1-functions", - "v1-usage", - "v1-usage-dump", + "v1-stats-resources", + "v1-stats-usage", + "v1-stats-usage-dump", "v1-webhooks", "v1-certificates", "v1-builds", @@ -12590,9 +12382,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12654,9 +12443,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12718,9 +12504,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12782,9 +12565,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12846,9 +12626,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12874,9 +12651,70 @@ ] } }, - "\/health\/queue\/usage": { + "\/health\/queue\/stats-resources": { "get": { - "summary": "Get usage queue", + "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", + "weight": 143, + "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" @@ -12896,12 +12734,12 @@ }, "x-appwrite": { "method": "getQueueUsage", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, "demo": "health\/get-queue-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -12910,9 +12748,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12938,10 +12773,10 @@ ] } }, - "\/health\/queue\/usage-dump": { + "\/health\/queue\/stats-usage-dump": { "get": { "summary": "Get usage dump queue", - "operationId": "healthGetQueueUsageDump", + "operationId": "healthGetQueueStatsUsageDump", "tags": [ "health" ], @@ -12959,13 +12794,13 @@ } }, "x-appwrite": { - "method": "getQueueUsageDump", - "weight": 144, + "method": "getQueueStatsUsageDump", + "weight": 145, "cookies": false, "type": "", "deprecated": false, - "demo": "health\/get-queue-usage-dump.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-usage-dump.md", + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -12974,9 +12809,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13038,9 +12870,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13088,7 +12917,7 @@ }, "x-appwrite": { "method": "getStorage", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -13102,9 +12931,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13139,7 +12965,7 @@ }, "x-appwrite": { "method": "getStorageLocal", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -13153,9 +12979,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13204,9 +13027,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13241,7 +13061,7 @@ }, "x-appwrite": { "method": "get", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -13257,9 +13077,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13295,7 +13112,7 @@ }, "x-appwrite": { "method": "listCodes", - "weight": 118, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -13311,9 +13128,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13349,7 +13163,7 @@ }, "x-appwrite": { "method": "listContinents", - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -13365,9 +13179,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13403,7 +13214,7 @@ }, "x-appwrite": { "method": "listCountries", - "weight": 119, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -13419,9 +13230,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13457,7 +13265,7 @@ }, "x-appwrite": { "method": "listCountriesEU", - "weight": 120, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -13473,9 +13281,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13511,7 +13316,7 @@ }, "x-appwrite": { "method": "listCountriesPhones", - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -13527,9 +13332,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -13565,7 +13367,7 @@ }, "x-appwrite": { "method": "listCurrencies", - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -13581,9 +13383,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13619,7 +13418,7 @@ }, "x-appwrite": { "method": "listLanguages", - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -13635,9 +13434,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13673,7 +13469,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -13688,9 +13484,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13751,7 +13544,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -13766,9 +13559,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13882,7 +13672,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -13897,7 +13687,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -13912,9 +13702,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14045,7 +13832,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -14060,9 +13847,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14120,7 +13904,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "x-example": "{}" }, "action": { @@ -14140,7 +13924,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "x-example": "<SOUND>" }, "color": { @@ -14154,9 +13938,9 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "x-example": null }, "draft": { "type": "boolean", @@ -14167,12 +13951,31 @@ "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", - "title", - "body" + "messageId" ] } } @@ -14187,7 +13990,7 @@ "tags": [ "messaging" ], - "description": "Update a push notification by its unique ID.\n", + "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", @@ -14202,7 +14005,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -14217,9 +14020,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14331,6 +14131,27 @@ "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": [] } } } @@ -14361,7 +14182,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -14376,9 +14197,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14457,7 +14275,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -14472,12 +14290,12 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 362, "cookies": false, "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.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}", @@ -14487,9 +14305,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14586,7 +14401,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -14601,9 +14416,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14641,7 +14453,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -14656,9 +14468,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14705,7 +14514,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -14720,9 +14529,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14782,7 +14588,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14797,9 +14603,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14859,7 +14662,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -14874,9 +14677,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14937,7 +14737,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -14952,9 +14752,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15044,7 +14841,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -15059,9 +14856,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15154,7 +14948,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -15169,9 +14963,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15241,7 +15032,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -15256,9 +15047,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15331,7 +15119,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -15346,9 +15134,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15448,7 +15233,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -15463,9 +15248,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15568,7 +15350,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -15583,9 +15365,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15665,7 +15444,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -15680,9 +15459,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15765,7 +15541,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -15780,9 +15556,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15872,7 +15645,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -15887,9 +15660,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15982,7 +15752,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -15997,9 +15767,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16127,7 +15894,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -16142,9 +15909,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16274,7 +16038,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -16289,9 +16053,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16371,7 +16132,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -16386,9 +16147,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16471,7 +16229,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -16486,9 +16244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16568,7 +16323,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -16583,9 +16338,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16668,7 +16420,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -16683,9 +16435,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16765,7 +16514,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -16780,9 +16529,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16865,7 +16611,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -16880,9 +16626,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16962,7 +16705,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -16977,9 +16720,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17062,7 +16802,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -17077,9 +16817,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17117,7 +16854,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -17132,9 +16869,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17181,7 +16915,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -17196,9 +16930,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17258,7 +16989,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -17273,9 +17004,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17335,7 +17063,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -17350,9 +17078,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17411,7 +17136,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -17426,9 +17151,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17496,7 +17218,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -17511,9 +17233,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17558,7 +17277,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -17573,9 +17292,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17637,7 +17353,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -17652,9 +17368,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17701,7 +17414,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -17716,9 +17429,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17778,7 +17488,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -17793,9 +17503,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17864,7 +17571,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -17881,9 +17588,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17956,7 +17660,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17971,9 +17675,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18021,7 +17722,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -18038,9 +17739,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18083,7 +17781,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18098,7 +17796,7 @@ }, "x-appwrite": { "method": "list", - "weight": 339, + "weight": 311, "cookies": false, "type": "", "deprecated": false, @@ -18112,9 +17810,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18159,7 +17854,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18174,7 +17869,7 @@ }, "x-appwrite": { "method": "createAppwriteMigration", - "weight": 334, + "weight": 306, "cookies": false, "type": "", "deprecated": false, @@ -18188,9 +17883,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18216,17 +17908,17 @@ }, "endpoint": { "type": "string", - "description": "Source's Appwrite Endpoint", + "description": "Source Appwrite endpoint", "x-example": "https:\/\/example.com" }, "projectId": { "type": "string", - "description": "Source's Project ID", + "description": "Source Project ID", "x-example": "<PROJECT_ID>" }, "apiKey": { "type": "string", - "description": "Source's API Key", + "description": "Source API Key", "x-example": "<API_KEY>" } }, @@ -18249,7 +17941,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18264,7 +17956,7 @@ }, "x-appwrite": { "method": "getAppwriteReport", - "weight": 341, + "weight": 313, "cookies": false, "type": "", "deprecated": false, @@ -18278,9 +17970,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18337,14 +18026,92 @@ ] } }, + "\/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", + "weight": 310, + "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": "Migrate Firebase data (Service Account)", + "summary": "Migrate Firebase data", "operationId": "migrationsCreateFirebaseMigration", "tags": [ "migrations" ], - "description": "", + "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", @@ -18359,7 +18126,7 @@ }, "x-appwrite": { "method": "createFirebaseMigration", - "weight": 336, + "weight": 307, "cookies": false, "type": "", "deprecated": false, @@ -18373,9 +18140,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18415,177 +18179,6 @@ } } }, - "\/migrations\/firebase\/deauthorize": { - "get": { - "summary": "Revoke Appwrite's authorization to access Firebase projects", - "operationId": "migrationsDeleteFirebaseAuth", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "File" - } - }, - "x-appwrite": { - "method": "deleteFirebaseAuth", - "weight": 347, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/delete-firebase-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, - "\/migrations\/firebase\/oauth": { - "post": { - "summary": "Migrate Firebase data (OAuth)", - "operationId": "migrationsCreateFirebaseOAuthMigration", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "202": { - "description": "Migration", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/migration" - } - } - } - } - }, - "x-appwrite": { - "method": "createFirebaseOAuthMigration", - "weight": 335, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/create-firebase-o-auth-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, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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" - } - }, - "projectId": { - "type": "string", - "description": "Project ID of the Firebase Project", - "x-example": "<PROJECT_ID>" - } - }, - "required": [ - "resources", - "projectId" - ] - } - } - } - } - } - }, - "\/migrations\/firebase\/projects": { - "get": { - "summary": "List Firebase projects", - "operationId": "migrationsListFirebaseProjects", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migrations Firebase Projects List", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/firebaseProjectList" - } - } - } - } - }, - "x-appwrite": { - "method": "listFirebaseProjects", - "weight": 346, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/list-firebase-projects.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.read", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, "\/migrations\/firebase\/report": { "get": { "summary": "Generate a report on Firebase data", @@ -18593,7 +18186,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18608,7 +18201,7 @@ }, "x-appwrite": { "method": "getFirebaseReport", - "weight": 342, + "weight": 314, "cookies": false, "type": "", "deprecated": false, @@ -18622,9 +18215,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18660,80 +18250,6 @@ ] } }, - "\/migrations\/firebase\/report\/oauth": { - "get": { - "summary": "Generate a report on Firebase data using OAuth", - "operationId": "migrationsGetFirebaseReportOAuth", - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migration Report", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/migrationReport" - } - } - } - } - }, - "x-appwrite": { - "method": "getFirebaseReportOAuth", - "weight": 343, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/get-firebase-report-o-auth.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, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ], - "parameters": [ - { - "name": "resources", - "description": "List of resources to migrate", - "required": true, - "schema": { - "type": "array", - "items": { - "type": "string" - } - }, - "in": "query" - }, - { - "name": "projectId", - "description": "Project ID", - "required": true, - "schema": { - "type": "string", - "x-example": "<PROJECT_ID>" - }, - "in": "query" - } - ] - } - }, "\/migrations\/nhost": { "post": { "summary": "Migrate NHost data", @@ -18741,7 +18257,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18756,7 +18272,7 @@ }, "x-appwrite": { "method": "createNHostMigration", - "weight": 338, + "weight": 309, "cookies": false, "type": "", "deprecated": false, @@ -18770,9 +18286,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18854,7 +18367,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18869,7 +18382,7 @@ }, "x-appwrite": { "method": "getNHostReport", - "weight": 349, + "weight": 316, "cookies": false, "type": "", "deprecated": false, @@ -18883,9 +18396,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18989,7 +18499,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19004,7 +18514,7 @@ }, "x-appwrite": { "method": "createSupabaseMigration", - "weight": 337, + "weight": 308, "cookies": false, "type": "", "deprecated": false, @@ -19018,9 +18528,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19096,7 +18603,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19111,7 +18618,7 @@ }, "x-appwrite": { "method": "getSupabaseReport", - "weight": 348, + "weight": 315, "cookies": false, "type": "", "deprecated": false, @@ -19125,9 +18632,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19222,7 +18726,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19237,7 +18741,7 @@ }, "x-appwrite": { "method": "get", - "weight": 340, + "weight": 312, "cookies": false, "type": "", "deprecated": false, @@ -19251,9 +18755,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19282,7 +18783,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Retry a failed migration. This endpoint allows you to retry a migration that has previously failed.", "responses": { "202": { "description": "Migration", @@ -19297,7 +18798,7 @@ }, "x-appwrite": { "method": "retry", - "weight": 350, + "weight": 317, "cookies": false, "type": "", "deprecated": false, @@ -19311,9 +18812,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19342,7 +18840,7 @@ "tags": [ "migrations" ], - "description": "", + "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" @@ -19350,7 +18848,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 351, + "weight": 318, "cookies": false, "type": "", "deprecated": false, @@ -19364,9 +18862,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19397,7 +18892,7 @@ "tags": [ "project" ], - "description": "", + "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", @@ -19412,12 +18907,12 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 196, + "weight": 197, "cookies": false, "type": "", "deprecated": false, "demo": "project\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -19426,9 +18921,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19502,7 +18994,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 198, + "weight": 199, "cookies": false, "type": "", "deprecated": false, @@ -19516,9 +19008,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19550,7 +19039,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 197, + "weight": 198, "cookies": false, "type": "", "deprecated": false, @@ -19564,9 +19053,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19591,6 +19077,11 @@ "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": [ @@ -19625,7 +19116,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 199, + "weight": 200, "cookies": false, "type": "", "deprecated": false, @@ -19639,9 +19130,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19685,7 +19173,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 200, + "weight": 201, "cookies": false, "type": "", "deprecated": false, @@ -19699,9 +19187,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19738,6 +19223,11 @@ "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": [ @@ -19762,7 +19252,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 201, + "weight": 202, "cookies": false, "type": "", "deprecated": false, @@ -19776,9 +19266,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19809,7 +19296,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all projects. You can use the query params to filter your results. ", "responses": { "200": { "description": "Projects List", @@ -19824,12 +19311,12 @@ }, "x-appwrite": { "method": "list", - "weight": 151, + "weight": 152, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/list.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -19838,9 +19325,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19883,7 +19367,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new project. You can create a maximum of 100 projects per account. ", "responses": { "201": { "description": "Project", @@ -19898,12 +19382,12 @@ }, "x-appwrite": { "method": "create", - "weight": 150, + "weight": 151, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -19912,9 +19396,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19950,8 +19431,7 @@ "description": "Project Region.", "x-example": "default", "enum": [ - "default", - "fra" + "default" ], "x-enum-name": null, "x-enum-keys": [] @@ -20020,7 +19500,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20035,12 +19515,12 @@ }, "x-appwrite": { "method": "get", - "weight": 152, + "weight": 153, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20049,9 +19529,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20080,7 +19557,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a project by its unique ID.", "responses": { "200": { "description": "Project", @@ -20095,12 +19572,12 @@ }, "x-appwrite": { "method": "update", - "weight": 153, + "weight": 154, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20109,9 +19586,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20204,7 +19678,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a project by its unique ID.", "responses": { "204": { "description": "No content" @@ -20212,12 +19686,12 @@ }, "x-appwrite": { "method": "delete", - "weight": 170, + "weight": 171, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20226,9 +19700,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20259,7 +19730,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20274,12 +19745,12 @@ }, "x-appwrite": { "method": "updateApiStatus", - "weight": 157, + "weight": 158, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-api-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20288,9 +19759,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20353,7 +19821,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20368,12 +19836,12 @@ }, "x-appwrite": { "method": "updateApiStatusAll", - "weight": 158, + "weight": 159, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-api-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20382,9 +19850,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20434,7 +19899,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update how long sessions created within a project should stay active for.", "responses": { "200": { "description": "Project", @@ -20449,12 +19914,12 @@ }, "x-appwrite": { "method": "updateAuthDuration", - "weight": 163, + "weight": 164, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-duration.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20463,9 +19928,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20515,7 +19977,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the maximum number of users allowed in this project. Set to 0 for unlimited users. ", "responses": { "200": { "description": "Project", @@ -20530,12 +19992,12 @@ }, "x-appwrite": { "method": "updateAuthLimit", - "weight": 162, + "weight": 163, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20544,9 +20006,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20596,7 +20055,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20611,12 +20070,12 @@ }, "x-appwrite": { "method": "updateAuthSessionsLimit", - "weight": 168, + "weight": 169, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-sessions-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20625,9 +20084,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20672,12 +20128,12 @@ }, "\/projects\/{projectId}\/auth\/memberships-privacy": { "patch": { - "summary": "Update project team sensitive attributes", + "summary": "Update project memberships privacy attributes", "operationId": "projectsUpdateMembershipsPrivacy", "tags": [ "projects" ], - "description": "", + "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", @@ -20692,12 +20148,12 @@ }, "x-appwrite": { "method": "updateMembershipsPrivacy", - "weight": 161, + "weight": 162, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-memberships-privacy.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20706,9 +20162,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20770,7 +20223,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the list of mock phone numbers for testing. Use these numbers to bypass SMS verification in development. ", "responses": { "200": { "description": "Project", @@ -20785,12 +20238,12 @@ }, "x-appwrite": { "method": "updateMockNumbers", - "weight": 169, + "weight": 170, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-mock-numbers.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20799,9 +20252,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20854,7 +20304,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20869,12 +20319,12 @@ }, "x-appwrite": { "method": "updateAuthPasswordDictionary", - "weight": 166, + "weight": 167, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-password-dictionary.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20883,9 +20333,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20935,7 +20382,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20950,12 +20397,12 @@ }, "x-appwrite": { "method": "updateAuthPasswordHistory", - "weight": 165, + "weight": 166, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-password-history.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20964,9 +20411,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21016,7 +20460,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21031,12 +20475,12 @@ }, "x-appwrite": { "method": "updatePersonalDataCheck", - "weight": 167, + "weight": 168, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-personal-data-check.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21045,9 +20489,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21097,7 +20538,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Enable or disable session email alerts. When enabled, users will receive email notifications when new sessions are created.", "responses": { "200": { "description": "Project", @@ -21112,12 +20553,12 @@ }, "x-appwrite": { "method": "updateSessionAlerts", - "weight": 160, + "weight": 161, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-session-alerts.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21126,9 +20567,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21178,7 +20616,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21193,12 +20631,12 @@ }, "x-appwrite": { "method": "updateAuthStatus", - "weight": 164, + "weight": 165, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21207,9 +20645,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21280,7 +20715,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new JWT token. This token can be used to authenticate users with custom scopes and expiration time. ", "responses": { "201": { "description": "JWT", @@ -21295,12 +20730,12 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 182, + "weight": 183, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create-j-w-t.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21309,9 +20744,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21369,7 +20801,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all API keys from the current project. ", "responses": { "200": { "description": "API Keys List", @@ -21384,12 +20816,12 @@ }, "x-appwrite": { "method": "listKeys", - "weight": 178, + "weight": 179, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/list-keys.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21398,9 +20830,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21429,7 +20858,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21444,12 +20873,12 @@ }, "x-appwrite": { "method": "createKey", - "weight": 177, + "weight": 178, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21458,9 +20887,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21524,7 +20950,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21539,12 +20965,12 @@ }, "x-appwrite": { "method": "getKey", - "weight": 179, + "weight": 180, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21553,9 +20979,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21594,7 +21017,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21609,12 +21032,12 @@ }, "x-appwrite": { "method": "updateKey", - "weight": 180, + "weight": 181, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21623,9 +21046,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21697,7 +21117,7 @@ "tags": [ "projects" ], - "description": "", + "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" @@ -21705,12 +21125,12 @@ }, "x-appwrite": { "method": "deleteKey", - "weight": 181, + "weight": 182, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21719,9 +21139,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21762,7 +21179,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21777,12 +21194,12 @@ }, "x-appwrite": { "method": "updateOAuth2", - "weight": 159, + "weight": 160, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-o-auth2.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21791,9 +21208,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21901,7 +21315,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21916,12 +21330,12 @@ }, "x-appwrite": { "method": "listPlatforms", - "weight": 184, + "weight": 185, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/list-platforms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21930,9 +21344,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21961,7 +21372,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21976,12 +21387,12 @@ }, "x-appwrite": { "method": "createPlatform", - "weight": 183, + "weight": 184, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21990,9 +21401,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22082,7 +21490,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22097,12 +21505,12 @@ }, "x-appwrite": { "method": "getPlatform", - "weight": 185, + "weight": 186, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22111,9 +21519,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22152,7 +21557,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22167,12 +21572,12 @@ }, "x-appwrite": { "method": "updatePlatform", - "weight": 186, + "weight": 187, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22181,9 +21586,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22256,7 +21658,7 @@ "tags": [ "projects" ], - "description": "", + "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" @@ -22264,12 +21666,12 @@ }, "x-appwrite": { "method": "deletePlatform", - "weight": 187, + "weight": 188, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22278,9 +21680,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22321,7 +21720,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of a specific service. Use this endpoint to enable or disable a service in your project. ", "responses": { "200": { "description": "Project", @@ -22336,12 +21735,12 @@ }, "x-appwrite": { "method": "updateServiceStatus", - "weight": 155, + "weight": 156, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-service-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22350,9 +21749,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22393,6 +21789,7 @@ "storage", "teams", "users", + "sites", "functions", "graphql", "messaging" @@ -22423,7 +21820,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of all services. Use this endpoint to enable or disable all optional services at once. ", "responses": { "200": { "description": "Project", @@ -22438,12 +21835,12 @@ }, "x-appwrite": { "method": "updateServiceStatusAll", - "weight": 156, + "weight": 157, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-service-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22452,9 +21849,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22504,7 +21898,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22519,12 +21913,12 @@ }, "x-appwrite": { "method": "updateSmtp", - "weight": 188, + "weight": 189, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-smtp.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22533,9 +21927,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22631,7 +22022,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Send a test email to verify SMTP configuration. ", "responses": { "204": { "description": "No content" @@ -22639,12 +22030,12 @@ }, "x-appwrite": { "method": "createSmtpTest", - "weight": 189, + "weight": 190, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create-smtp-test.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22653,9 +22044,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22757,7 +22145,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the team ID of a project allowing for it to be transferred to another team.", "responses": { "200": { "description": "Project", @@ -22772,12 +22160,12 @@ }, "x-appwrite": { "method": "updateTeam", - "weight": 154, + "weight": 155, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-team.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22786,9 +22174,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22838,7 +22223,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22853,12 +22238,12 @@ }, "x-appwrite": { "method": "getEmailTemplate", - "weight": 191, + "weight": 192, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22867,9 +22252,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23064,14 +22446,14 @@ "tags": [ "projects" ], - "description": "", + "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": "Project", + "description": "EmailTemplate", "content": { "application\/json": { "schema": { - "$ref": "#\/components\/schemas\/project" + "$ref": "#\/components\/schemas\/emailTemplate" } } } @@ -23079,12 +22461,12 @@ }, "x-appwrite": { "method": "updateEmailTemplate", - "weight": 193, + "weight": 194, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23093,9 +22475,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23330,7 +22709,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -23345,12 +22724,12 @@ }, "x-appwrite": { "method": "deleteEmailTemplate", - "weight": 195, + "weight": 196, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23359,9 +22738,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23558,7 +22934,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a custom SMS template for the specified locale and type returning it's contents.", "responses": { "200": { "description": "SmsTemplate", @@ -23573,12 +22949,12 @@ }, "x-appwrite": { "method": "getSmsTemplate", - "weight": 190, + "weight": 191, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23587,9 +22963,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23781,7 +23154,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -23796,12 +23169,12 @@ }, "x-appwrite": { "method": "updateSmsTemplate", - "weight": 192, + "weight": 193, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23810,9 +23183,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24023,7 +23393,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24038,12 +23408,12 @@ }, "x-appwrite": { "method": "deleteSmsTemplate", - "weight": 194, + "weight": 195, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24052,9 +23422,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24248,7 +23615,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24263,12 +23630,12 @@ }, "x-appwrite": { "method": "listWebhooks", - "weight": 172, + "weight": 173, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/list-webhooks.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24277,9 +23644,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24308,7 +23672,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24323,12 +23687,12 @@ }, "x-appwrite": { "method": "createWebhook", - "weight": 171, + "weight": 172, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24337,9 +23701,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24425,7 +23786,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a webhook by its unique ID. This endpoint returns details about a specific webhook configured for a project. ", "responses": { "200": { "description": "Webhook", @@ -24440,12 +23801,12 @@ }, "x-appwrite": { "method": "getWebhook", - "weight": 173, + "weight": 174, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24454,9 +23815,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24495,7 +23853,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24510,12 +23868,12 @@ }, "x-appwrite": { "method": "updateWebhook", - "weight": 174, + "weight": 175, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24524,9 +23882,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24620,7 +23975,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a webhook by its unique ID. Once deleted, the webhook will no longer receive project events. ", "responses": { "204": { "description": "No content" @@ -24628,12 +23983,12 @@ }, "x-appwrite": { "method": "deleteWebhook", - "weight": 176, + "weight": 177, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24642,9 +23997,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24685,7 +24037,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24700,12 +24052,12 @@ }, "x-appwrite": { "method": "updateWebhookSignature", - "weight": 175, + "weight": 176, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-webhook-signature.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24714,9 +24066,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24772,7 +24121,7 @@ }, "x-appwrite": { "method": "listRules", - "weight": 317, + "weight": 289, "cookies": false, "type": "", "deprecated": false, @@ -24786,9 +24135,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24801,7 +24147,7 @@ "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, resourceType, resourceId, url", + "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", @@ -24824,14 +24170,16 @@ "in": "query" } ] - }, + } + }, + "\/proxy\/rules\/api": { "post": { - "summary": "Create rule", - "operationId": "proxyCreateRule", + "summary": "Create API rule", + "operationId": "proxyCreateAPIRule", "tags": [ "proxy" ], - "description": "Create a new proxy rule.", + "description": "Create a new proxy rule for serving Appwrite's API on custom domain.", "responses": { "201": { "description": "Rule", @@ -24845,24 +24193,87 @@ } }, "x-appwrite": { - "method": "createRule", - "weight": 316, + "method": "createAPIRule", + "weight": 425, "cookies": false, "type": "", "deprecated": false, - "demo": "proxy\/create-rule.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/create-rule.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", + "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", + "weight": 427, + "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, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24883,26 +24294,188 @@ "description": "Domain name.", "x-example": null }, - "resourceType": { + "functionId": { "type": "string", - "description": "Action definition for the rule. Possible values are \"api\", \"function\"", - "x-example": "api", - "enum": [ - "api", - "function" - ], - "x-enum-name": null, - "x-enum-keys": [] + "description": "ID of function to be executed.", + "x-example": "<FUNCTION_ID>" }, - "resourceId": { + "branch": { "type": "string", - "description": "ID of resource for the action type. If resourceType is \"api\", leave empty. If resourceType is \"function\", provide ID of the function.", - "x-example": "<RESOURCE_ID>" + "description": "Name of VCS branch to deploy changes automatically", + "x-example": "<BRANCH>" } }, "required": [ "domain", - "resourceType" + "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", + "weight": 428, + "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" + ] + } + }, + "required": [ + "domain", + "url", + "statusCode" + ] + } + } + } + } + } + }, + "\/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", + "weight": 426, + "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" ] } } @@ -24932,7 +24505,7 @@ }, "x-appwrite": { "method": "getRule", - "weight": 318, + "weight": 290, "cookies": false, "type": "", "deprecated": false, @@ -24946,9 +24519,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24985,7 +24555,7 @@ }, "x-appwrite": { "method": "deleteRule", - "weight": 319, + "weight": 291, "cookies": false, "type": "", "deprecated": false, @@ -24999,9 +24569,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25032,7 +24599,7 @@ "tags": [ "proxy" ], - "description": "", + "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", @@ -25047,12 +24614,12 @@ }, "x-appwrite": { "method": "updateRuleVerification", - "weight": 320, + "weight": 292, "cookies": false, "type": "", "deprecated": false, "demo": "proxy\/update-rule-verification.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -25061,9 +24628,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25087,6 +24651,2485 @@ ] } }, + "\/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", + "weight": 397, + "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", + "weight": 395, + "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", + "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", + "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" + ], + "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", + "weight": 400, + "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", + "weight": 423, + "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", + "weight": 419, + "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", + "weight": 420, + "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", + "weight": 421, + "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", + "weight": 396, + "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", + "weight": 398, + "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", + "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", + "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" + ], + "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", + "weight": 399, + "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", + "weight": 406, + "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", + "weight": 405, + "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", + "weight": 401, + "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", + "weight": 409, + "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", + "weight": 402, + "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", + "weight": 403, + "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", + "weight": 404, + "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", + "weight": 407, + "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": "Download deployment", + "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", + "weight": 408, + "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", + "weight": 410, + "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", + "weight": 412, + "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", + "weight": 411, + "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", + "weight": 413, + "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", + "weight": 422, + "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", + "weight": 416, + "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", + "weight": 414, + "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", + "weight": 415, + "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", + "weight": 417, + "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", + "weight": 418, + "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", @@ -25109,7 +27152,7 @@ }, "x-appwrite": { "method": "listBuckets", - "weight": 203, + "weight": 204, "cookies": false, "type": "", "deprecated": false, @@ -25123,9 +27166,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25184,7 +27224,7 @@ }, "x-appwrite": { "method": "createBucket", - "weight": 202, + "weight": 203, "cookies": false, "type": "", "deprecated": false, @@ -25198,9 +27238,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25313,7 +27350,7 @@ }, "x-appwrite": { "method": "getBucket", - "weight": 204, + "weight": 205, "cookies": false, "type": "", "deprecated": false, @@ -25327,9 +27364,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25374,7 +27408,7 @@ }, "x-appwrite": { "method": "updateBucket", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -25388,9 +27422,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25500,7 +27531,7 @@ }, "x-appwrite": { "method": "deleteBucket", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -25514,9 +27545,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25563,7 +27591,7 @@ }, "x-appwrite": { "method": "listFiles", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -25579,9 +27607,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25651,7 +27676,7 @@ }, "x-appwrite": { "method": "createFile", - "weight": 207, + "weight": 208, "cookies": false, "type": "upload", "deprecated": false, @@ -25667,9 +27692,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25751,7 +27773,7 @@ }, "x-appwrite": { "method": "getFile", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -25767,9 +27789,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25825,7 +27844,7 @@ }, "x-appwrite": { "method": "updateFile", - "weight": 214, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -25841,9 +27860,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25916,7 +27932,7 @@ }, "x-appwrite": { "method": "deleteFile", - "weight": 215, + "weight": 216, "cookies": false, "type": "", "deprecated": false, @@ -25932,9 +27948,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25985,7 +27998,7 @@ }, "x-appwrite": { "method": "getFileDownload", - "weight": 211, + "weight": 212, "cookies": false, "type": "location", "deprecated": false, @@ -26001,9 +28014,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26054,7 +28064,7 @@ }, "x-appwrite": { "method": "getFilePreview", - "weight": 210, + "weight": 211, "cookies": false, "type": "location", "deprecated": false, @@ -26070,9 +28080,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26246,6 +28253,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -26272,7 +28280,7 @@ }, "x-appwrite": { "method": "getFileView", - "weight": 212, + "weight": 213, "cookies": false, "type": "location", "deprecated": false, @@ -26288,9 +28296,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26333,7 +28338,7 @@ "tags": [ "storage" ], - "description": "", + "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", @@ -26348,12 +28353,12 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 216, + "weight": 217, "cookies": false, "type": "", "deprecated": false, "demo": "storage\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -26362,9 +28367,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26407,7 +28409,7 @@ "tags": [ "storage" ], - "description": "", + "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", @@ -26422,12 +28424,12 @@ }, "x-appwrite": { "method": "getBucketUsage", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, "demo": "storage\/get-bucket-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -26436,9 +28438,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26506,7 +28505,7 @@ }, "x-appwrite": { "method": "list", - "weight": 219, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -26522,9 +28521,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26584,7 +28580,7 @@ }, "x-appwrite": { "method": "create", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -26600,9 +28596,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26671,7 +28664,7 @@ }, "x-appwrite": { "method": "get", - "weight": 220, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -26687,9 +28680,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26735,7 +28725,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -26751,9 +28741,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26811,7 +28798,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -26827,9 +28814,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26877,7 +28861,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -26891,9 +28875,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26952,7 +28933,7 @@ }, "x-appwrite": { "method": "listMemberships", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -26968,9 +28949,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26995,7 +28973,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: userId, teamId, invited, joined, confirm", + "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", @@ -27040,7 +29018,7 @@ }, "x-appwrite": { "method": "createMembership", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -27056,9 +29034,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27153,7 +29128,7 @@ }, "x-appwrite": { "method": "getMembership", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -27169,9 +29144,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27227,7 +29199,7 @@ }, "x-appwrite": { "method": "updateMembership", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -27243,9 +29215,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27316,7 +29285,7 @@ }, "x-appwrite": { "method": "deleteMembership", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -27332,9 +29301,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27392,7 +29358,7 @@ }, "x-appwrite": { "method": "updateMembershipStatus", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -27407,9 +29373,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27491,7 +29454,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -27506,9 +29469,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27553,7 +29513,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -27568,9 +29528,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27636,7 +29593,7 @@ }, "x-appwrite": { "method": "list", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -27650,9 +29607,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27711,7 +29665,7 @@ }, "x-appwrite": { "method": "create", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -27725,9 +29679,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27801,7 +29752,7 @@ }, "x-appwrite": { "method": "createArgon2User", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -27815,9 +29766,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27888,7 +29836,7 @@ }, "x-appwrite": { "method": "createBcryptUser", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -27902,9 +29850,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27975,7 +29920,7 @@ }, "x-appwrite": { "method": "listIdentities", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -27989,9 +29934,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28045,7 +29987,7 @@ }, "x-appwrite": { "method": "deleteIdentity", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -28059,9 +30001,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28108,7 +30047,7 @@ }, "x-appwrite": { "method": "createMD5User", - "weight": 234, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -28122,9 +30061,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28195,7 +30131,7 @@ }, "x-appwrite": { "method": "createPHPassUser", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -28209,9 +30145,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28282,7 +30215,7 @@ }, "x-appwrite": { "method": "createScryptUser", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -28296,9 +30229,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28399,7 +30329,7 @@ }, "x-appwrite": { "method": "createScryptModifiedUser", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -28413,9 +30343,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28504,7 +30431,7 @@ }, "x-appwrite": { "method": "createSHAUser", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -28518,9 +30445,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28596,7 +30520,7 @@ "tags": [ "users" ], - "description": "", + "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", @@ -28611,12 +30535,12 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 274, + "weight": 275, "cookies": false, "type": "", "deprecated": false, "demo": "users\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -28625,9 +30549,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28685,7 +30606,7 @@ }, "x-appwrite": { "method": "get", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -28699,9 +30620,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28739,7 +30657,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -28753,9 +30671,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28802,7 +30717,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -28816,9 +30731,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28884,7 +30796,7 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -28898,9 +30810,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28968,7 +30877,7 @@ }, "x-appwrite": { "method": "updateLabels", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -28982,9 +30891,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29053,7 +30959,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -29067,9 +30973,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29129,7 +31032,7 @@ }, "x-appwrite": { "method": "listMemberships", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -29143,9 +31046,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29166,6 +31066,30 @@ "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" } ] } @@ -29192,7 +31116,7 @@ }, "x-appwrite": { "method": "updateMfa", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -29206,9 +31130,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29261,20 +31182,13 @@ ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/user" - } - } - } + "204": { + "description": "No content" } }, "x-appwrite": { "method": "deleteMfaAuthenticator", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -29288,9 +31202,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29352,7 +31263,7 @@ }, "x-appwrite": { "method": "listMfaFactors", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -29366,9 +31277,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29415,7 +31323,7 @@ }, "x-appwrite": { "method": "getMfaRecoveryCodes", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -29429,9 +31337,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29476,7 +31381,7 @@ }, "x-appwrite": { "method": "updateMfaRecoveryCodes", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -29490,9 +31395,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29537,7 +31439,7 @@ }, "x-appwrite": { "method": "createMfaRecoveryCodes", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -29551,9 +31453,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29600,7 +31499,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -29614,9 +31513,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29682,7 +31578,7 @@ }, "x-appwrite": { "method": "updatePassword", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -29696,9 +31592,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29764,7 +31657,7 @@ }, "x-appwrite": { "method": "updatePhone", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -29778,9 +31671,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29846,7 +31736,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -29860,9 +31750,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29907,7 +31794,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -29921,9 +31808,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29989,7 +31873,7 @@ }, "x-appwrite": { "method": "listSessions", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -30003,9 +31887,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30050,7 +31931,7 @@ }, "x-appwrite": { "method": "createSession", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -30064,9 +31945,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30104,7 +31982,7 @@ }, "x-appwrite": { "method": "deleteSessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -30118,9 +31996,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30160,7 +32035,7 @@ }, "x-appwrite": { "method": "deleteSession", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -30174,9 +32049,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30233,7 +32105,7 @@ }, "x-appwrite": { "method": "updateStatus", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -30247,9 +32119,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30315,7 +32184,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -30330,9 +32199,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30390,7 +32256,7 @@ }, "x-appwrite": { "method": "createTarget", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -30405,9 +32271,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30502,7 +32365,7 @@ }, "x-appwrite": { "method": "getTarget", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -30517,9 +32380,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30574,7 +32434,7 @@ }, "x-appwrite": { "method": "updateTarget", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -30589,9 +32449,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30665,7 +32522,7 @@ }, "x-appwrite": { "method": "deleteTarget", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -30680,9 +32537,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30739,7 +32593,7 @@ }, "x-appwrite": { "method": "createToken", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -30753,9 +32607,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30823,7 +32674,7 @@ }, "x-appwrite": { "method": "updateEmailVerification", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -30837,9 +32688,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30905,7 +32753,7 @@ }, "x-appwrite": { "method": "updatePhoneVerification", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -30919,9 +32767,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30965,6 +32810,101 @@ } } }, + "\/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", + "weight": 279, + "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", @@ -30972,14 +32912,14 @@ "tags": [ "vcs" ], - "description": "", + "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": "Provider Repositories List", + "description": "Framework Provider Repositories List", "content": { "application\/json": { "schema": { - "$ref": "#\/components\/schemas\/providerRepositoryList" + "$ref": "#\/components\/schemas\/providerRepositoryFrameworkList" } } } @@ -30987,12 +32927,12 @@ }, "x-appwrite": { "method": "listRepositories", - "weight": 279, + "weight": 280, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/list-repositories.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31001,9 +32941,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31024,6 +32961,22 @@ }, "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.", @@ -31043,7 +32996,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31058,12 +33011,12 @@ }, "x-appwrite": { "method": "createRepository", - "weight": 280, + "weight": 281, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/create-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31072,9 +33025,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31130,7 +33080,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31145,12 +33095,12 @@ }, "x-appwrite": { "method": "getRepository", - "weight": 281, + "weight": 282, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/get-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31159,9 +33109,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31202,7 +33149,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31217,12 +33164,12 @@ }, "x-appwrite": { "method": "listRepositoryBranches", - "weight": 282, + "weight": 283, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/list-repository-branches.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31231,9 +33178,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31274,7 +33218,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31289,12 +33233,12 @@ }, "x-appwrite": { "method": "getRepositoryContents", - "weight": 277, + "weight": 278, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/get-repository-contents.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31303,9 +33247,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31350,94 +33291,6 @@ ] } }, - "\/vcs\/github\/installations\/{installationId}\/providerRepositories\/{providerRepositoryId}\/detection": { - "post": { - "summary": "Detect runtime settings from source code", - "operationId": "vcsCreateRepositoryDetection", - "tags": [ - "vcs" - ], - "description": "", - "responses": { - "200": { - "description": "Detection", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/detection" - } - } - } - } - }, - "x-appwrite": { - "method": "createRepositoryDetection", - "weight": 278, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "vcs\/create-repository-detection.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "vcs.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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" - } - ], - "requestBody": { - "content": { - "application\/json": { - "schema": { - "type": "object", - "properties": { - "providerRootDirectory": { - "type": "string", - "description": "Path to Root Directory", - "x-example": "<PROVIDER_ROOT_DIRECTORY>" - } - } - } - } - } - } - } - }, "\/vcs\/github\/installations\/{installationId}\/repositories\/{repositoryId}": { "patch": { "summary": "Authorize external deployment", @@ -31445,7 +33298,7 @@ "tags": [ "vcs" ], - "description": "", + "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" @@ -31453,12 +33306,12 @@ }, "x-appwrite": { "method": "updateExternalDeployments", - "weight": 287, + "weight": 288, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/update-external-deployments.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31467,9 +33320,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31529,7 +33379,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31544,7 +33394,7 @@ }, "x-appwrite": { "method": "listInstallations", - "weight": 284, + "weight": 285, "cookies": false, "type": "", "deprecated": false, @@ -31558,9 +33408,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31605,7 +33452,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31620,7 +33467,7 @@ }, "x-appwrite": { "method": "getInstallation", - "weight": 285, + "weight": 286, "cookies": false, "type": "", "deprecated": false, @@ -31634,9 +33481,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31665,7 +33509,7 @@ "tags": [ "vcs" ], - "description": "", + "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" @@ -31673,7 +33517,7 @@ }, "x-appwrite": { "method": "deleteInstallation", - "weight": 286, + "weight": 287, "cookies": false, "type": "", "deprecated": false, @@ -31687,9 +33531,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31767,6 +33608,11 @@ "description": "The Users service allows you to manage your project users.", "x-globalAttributes": [] }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, { "name": "functions", "description": "The Functions Service allows you view, create and manage your Cloud Functions.", @@ -32125,6 +33971,54 @@ "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", @@ -32197,28 +34091,52 @@ "installations" ] }, - "providerRepositoryList": { - "description": "Provider Repositories List", + "providerRepositoryFrameworkList": { + "description": "Framework Provider Repositories List", "type": "object", "properties": { "total": { "type": "integer", - "description": "Total number of providerRepositories documents that matched your query.", + "description": "Total number of frameworkProviderRepositories documents that matched your query.", "x-example": 5, "format": "int32" }, - "providerRepositories": { + "frameworkProviderRepositories": { "type": "array", - "description": "List of providerRepositories.", + "description": "List of frameworkProviderRepositories.", "items": { - "$ref": "#\/components\/schemas\/providerRepository" + "$ref": "#\/components\/schemas\/providerRepositoryFramework" }, "x-example": "" } }, "required": [ "total", - "providerRepositories" + "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": { @@ -32245,6 +34163,30 @@ "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", @@ -32749,30 +34691,6 @@ "migrations" ] }, - "firebaseProjectList": { - "description": "Migrations Firebase 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\/firebaseProject" - }, - "x-example": "" - } - }, - "required": [ - "total", - "projects" - ] - }, "specificationList": { "description": "Specifications List", "type": "object", @@ -35026,6 +36944,349 @@ "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", @@ -35070,19 +37331,39 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "x-example": false }, "runtime": { "type": "string", - "description": "Function execution runtime.", + "description": "Function execution and build runtime.", "x-example": "python-3.8" }, - "deployment": { + "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.", @@ -35109,7 +37390,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { @@ -35174,7 +37455,11 @@ "live", "logging", "runtime", - "deployment", + "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "scopes", "vars", "events", @@ -35371,6 +37656,11 @@ "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.", @@ -35391,6 +37681,7 @@ "name", "description", "value", + "secret", "placeholder", "required", "type" @@ -35469,11 +37760,6 @@ "description": "Is VCS (Version Control System) repository private?", "x-example": true }, - "runtime": { - "type": "string", - "description": "Auto-detected runtime suggestion. Empty if getting response of getRuntime().", - "x-example": "node" - }, "pushedAt": { "type": "string", "description": "Last commit date in ISO 8601 format.", @@ -35486,22 +37772,165 @@ "organization", "provider", "private", - "runtime", "pushedAt" ] }, - "detection": { - "description": "Detection", + "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" + "runtime", + "entrypoint", + "commands" ] }, "vcsContent": { @@ -35604,6 +38033,99 @@ "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", @@ -35643,7 +38165,7 @@ "description": "The entrypoint file to use to execute the deployment code.", "x-example": "index.js" }, - "size": { + "sourceSize": { "type": "integer", "description": "The code size in bytes.", "x-example": 128, @@ -35655,6 +38177,12 @@ "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.", @@ -35665,9 +38193,19 @@ "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 \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".", + "description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", "x-example": "ready" }, "buildLogs": { @@ -35675,7 +38213,7 @@ "description": "The build logs.", "x-example": "Compiling source files..." }, - "buildTime": { + "buildDuration": { "type": "integer", "description": "The current build time in seconds.", "x-example": 128, @@ -35740,13 +38278,16 @@ "resourceId", "resourceType", "entrypoint", - "size", + "sourceSize", "buildSize", + "totalSize", "buildId", "activate", + "screenshotLight", + "screenshotDark", "status", "buildLogs", - "buildTime", + "buildDuration", "providerRepositoryName", "providerRepositoryOwner", "providerRepositoryUrl", @@ -35860,7 +38401,7 @@ }, "duration": { "type": "number", - "description": "Function execution duration in seconds.", + "description": "Resource(function\/site) execution duration in seconds.", "x-example": 0.4, "format": "double" }, @@ -35890,70 +38431,6 @@ "duration" ] }, - "build": { - "description": "Build", - "type": "object", - "properties": { - "$id": { - "type": "string", - "description": "Build ID.", - "x-example": "5e5ea5c16897e" - }, - "deploymentId": { - "type": "string", - "description": "The deployment that created this build.", - "x-example": "5e5ea5c16897e" - }, - "status": { - "type": "string", - "description": "The build status. There are a few different types and each one means something different. \\nFailed - The deployment build has failed. More details can usually be found in buildStderr\\nReady - The deployment build was successful and the deployment is ready to be deployed\\nProcessing - The deployment is currently waiting to have a build triggered\\nBuilding - The deployment is currently being built", - "x-example": "ready" - }, - "stdout": { - "type": "string", - "description": "The stdout of the build.", - "x-example": "" - }, - "stderr": { - "type": "string", - "description": "The stderr of the build.", - "x-example": "" - }, - "startTime": { - "type": "string", - "description": "The deployment creation date in ISO 8601 format.", - "x-example": "2020-10-15T06:38:00.000+00:00" - }, - "endTime": { - "type": "string", - "description": "The time the build was finished in ISO 8601 format.", - "x-example": "2020-10-15T06:38:00.000+00:00" - }, - "duration": { - "type": "integer", - "description": "The build duration in seconds.", - "x-example": 0, - "format": "int32" - }, - "size": { - "type": "integer", - "description": "The code size in bytes.", - "x-example": 128, - "format": "int32" - } - }, - "required": [ - "$id", - "deploymentId", - "status", - "stdout", - "stderr", - "startTime", - "endTime", - "duration", - "size" - ] - }, "project": { "description": "Project", "type": "object", @@ -36077,17 +38554,17 @@ "description": "Whether or not to send session alert emails to users.", "x-example": true }, - "membershipsUserName": { + "authMembershipsUserName": { "type": "boolean", "description": "Whether or not to show user names in the teams membership response.", "x-example": true }, - "membershipsUserEmail": { + "authMembershipsUserEmail": { "type": "boolean", "description": "Whether or not to show user emails in the teams membership response.", "x-example": true }, - "membershipsMfa": { + "authMembershipsMfa": { "type": "boolean", "description": "Whether or not to show user MFA status in the teams membership response.", "x-example": true @@ -36258,6 +38735,11 @@ "description": "Users service status", "x-example": true }, + "serviceStatusForSites": { + "type": "boolean", + "description": "Sites service status", + "x-example": true + }, "serviceStatusForFunctions": { "type": "boolean", "description": "Functions service status", @@ -36297,9 +38779,9 @@ "authPersonalDataCheck", "authMockNumbers", "authSessionAlerts", - "membershipsUserName", - "membershipsUserEmail", - "membershipsMfa", + "authMembershipsUserName", + "authMembershipsUserEmail", + "authMembershipsMfa", "oAuthProviders", "platforms", "webhooks", @@ -36330,6 +38812,7 @@ "serviceStatusForStorage", "serviceStatusForTeams", "serviceStatusForUsers", + "serviceStatusForSites", "serviceStatusForFunctions", "serviceStatusForGraphql", "serviceStatusForMessaging" @@ -36648,6 +39131,11 @@ "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\"", @@ -36665,6 +39153,7 @@ "$updatedAt", "key", "value", + "secret", "resourceType", "resourceId" ] @@ -36976,7 +39465,8 @@ "resourceId": { "type": "string", "description": "Resource ID.", - "x-example": "5e5ea5c16897e" + "x-example": "5e5ea5c16897e", + "nullable": true }, "name": { "type": "string", @@ -36988,10 +39478,16 @@ "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": [ - "resourceId", "name", "value" ] @@ -37029,6 +39525,18 @@ "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.", @@ -37060,6 +39568,22 @@ "$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": [ @@ -37068,10 +39592,14 @@ "collectionsTotal", "documentsTotal", "storageTotal", + "databasesReadsTotal", + "databasesWritesTotal", "databases", "collections", "documents", - "storage" + "storage", + "databasesReads", + "databasesWrites" ] }, "usageDatabase": { @@ -37101,6 +39629,18 @@ "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.", @@ -37124,6 +39664,22 @@ "$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": [ @@ -37131,9 +39687,13 @@ "collectionsTotal", "documentsTotal", "storageTotal", + "databaseReadsTotal", + "databaseWritesTotal", "collections", "documents", - "storage" + "storage", + "databaseReads", + "databaseWrites" ] }, "usageCollection": { @@ -37310,6 +39870,20 @@ "$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": [ @@ -37317,7 +39891,9 @@ "filesTotal", "filesStorageTotal", "files", - "storage" + "storage", + "imageTransformations", + "imageTransformationsTotal" ] }, "usageFunctions": { @@ -37413,6 +39989,18 @@ }, "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.", @@ -37468,6 +40056,22 @@ "$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": [ @@ -37485,13 +40089,17 @@ "functions", "deployments", "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", "builds", "buildsStorage", "buildsTime", "buildsMbSeconds", "executions", "executionsTime", - "executionsMbSeconds" + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed" ] }, "usageFunction": { @@ -37521,6 +40129,18 @@ "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.", @@ -37533,6 +40153,12 @@ "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.", @@ -37628,6 +40254,269 @@ "$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": [ @@ -37643,13 +40532,270 @@ "executionsMbSecondsTotal", "deployments", "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", "builds", "buildsStorage", "buildsTime", "buildsMbSeconds", "executions", "executionsTime", - "executionsMbSeconds" + "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": { @@ -37728,6 +40874,18 @@ "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.", @@ -37807,6 +40965,56 @@ "$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": [ @@ -37822,6 +41030,8 @@ "bucketsTotal", "executionsMbSecondsTotal", "buildsMbSecondsTotal", + "databasesReadsTotal", + "databasesWritesTotal", "requests", "network", "users", @@ -37831,7 +41041,14 @@ "databasesStorageBreakdown", "executionsMbSecondsBreakdown", "buildsMbSecondsBreakdown", - "functionsStorageBreakdown" + "functionsStorageBreakdown", + "authPhoneTotal", + "authPhoneEstimate", + "authPhoneCountryBreakdown", + "databasesReads", + "databasesWrites", + "imageTransformations", + "imageTransformationsTotal" ] }, "headers": { @@ -37912,15 +41129,46 @@ "description": "Domain name.", "x-example": "appwrite.company.com" }, - "resourceType": { + "type": { "type": "string", - "description": "Action definition for the rule. Possible values are \"api\", \"function\", or \"redirect\"", + "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" }, - "resourceId": { + "deploymentResourceId": { "type": "string", - "description": "ID of resource for the action type. If resourceType is \"api\" or \"url\", it is empty. If resourceType is \"function\", it is ID of the function.", - "x-example": "myAwesomeFunction" + "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", @@ -37943,8 +41191,14 @@ "$createdAt", "$updatedAt", "domain", - "resourceType", - "resourceId", + "type", + "trigger", + "redirectUrl", + "redirectStatusCode", + "deploymentId", + "deploymentResourceType", + "deploymentResourceId", + "deploymentVcsProviderBranch", "status", "logs", "renewAt" @@ -38030,18 +41284,28 @@ "description": "Console Variables", "type": "object", "properties": { - "_APP_DOMAIN_TARGET": { + "_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_FUNCTIONS_SIZE_LIMIT": { + "_APP_COMPUTE_SIZE_LIMIT": { "type": "integer", "description": "Maximum file size allowed for deployment in bytes.", "x-example": "30000000", @@ -38066,16 +41330,42 @@ "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", + "_APP_DOMAIN_TARGET_CNAME", + "_APP_DOMAIN_TARGET_A", + "_APP_DOMAIN_TARGET_AAAA", "_APP_STORAGE_LIMIT", - "_APP_FUNCTIONS_SIZE_LIMIT", + "_APP_COMPUTE_SIZE_LIMIT", "_APP_USAGE_STATS", "_APP_VCS_ENABLED", "_APP_DOMAIN_ENABLED", - "_APP_ASSISTANT_ENABLED" + "_APP_ASSISTANT_ENABLED", + "_APP_DOMAIN_SITES", + "_APP_DOMAIN_FUNCTIONS", + "_APP_OPTIONS_FORCE_HTTPS", + "_APP_DOMAINS_NAMESERVERS" ] }, "mfaChallenge": { @@ -38605,6 +41895,11 @@ "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.", @@ -38633,6 +41928,7 @@ "source", "destination", "resources", + "resourceId", "statusCounters", "resourceData", "errors" @@ -38707,26 +42003,6 @@ "size", "version" ] - }, - "firebaseProject": { - "description": "MigrationFirebaseProject", - "type": "object", - "properties": { - "projectId": { - "type": "string", - "description": "Project ID.", - "x-example": "my-project" - }, - "displayName": { - "type": "string", - "description": "Project display name.", - "x-example": "My Project" - } - }, - "required": [ - "projectId", - "displayName" - ] } }, "securitySchemes": { diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index e84b751743..df5948090b 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.6.0", + "version": "1.7.0", "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", @@ -43,7 +43,7 @@ }, "x-appwrite": { "method": "get", - "weight": 9, + "weight": 10, "cookies": false, "type": "", "deprecated": false, @@ -58,9 +58,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -95,7 +92,7 @@ }, "x-appwrite": { "method": "create", - "weight": 8, + "weight": 9, "cookies": false, "type": "", "deprecated": false, @@ -110,9 +107,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -182,7 +176,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 34, + "weight": 35, "cookies": false, "type": "", "deprecated": false, @@ -197,9 +191,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -261,7 +252,7 @@ }, "x-appwrite": { "method": "listIdentities", - "weight": 57, + "weight": 58, "cookies": false, "type": "", "deprecated": false, @@ -276,9 +267,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -323,7 +311,7 @@ }, "x-appwrite": { "method": "deleteIdentity", - "weight": 58, + "weight": 59, "cookies": false, "type": "", "deprecated": false, @@ -338,9 +326,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -389,7 +374,7 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 29, + "weight": 30, "cookies": false, "type": "", "deprecated": false, @@ -404,9 +389,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -440,7 +422,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 31, + "weight": 32, "cookies": false, "type": "", "deprecated": false, @@ -455,9 +437,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -509,7 +488,7 @@ }, "x-appwrite": { "method": "updateMFA", - "weight": 44, + "weight": 45, "cookies": false, "type": "", "deprecated": false, @@ -524,9 +503,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -582,7 +558,7 @@ }, "x-appwrite": { "method": "createMfaAuthenticator", - "weight": 46, + "weight": 47, "cookies": false, "type": "", "deprecated": false, @@ -597,9 +573,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -651,7 +624,7 @@ }, "x-appwrite": { "method": "updateMfaAuthenticator", - "weight": 47, + "weight": 48, "cookies": false, "type": "", "deprecated": false, @@ -666,9 +639,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -732,7 +702,7 @@ }, "x-appwrite": { "method": "deleteMfaAuthenticator", - "weight": 51, + "weight": 52, "cookies": false, "type": "", "deprecated": false, @@ -747,9 +717,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -803,7 +770,7 @@ }, "x-appwrite": { "method": "createMfaChallenge", - "weight": 52, + "weight": 53, "cookies": false, "type": "", "deprecated": false, @@ -818,9 +785,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -866,10 +830,10 @@ ], "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": { - "204": { - "description": "No content", + "200": { + "description": "Session", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/session" } @@ -879,7 +843,7 @@ }, "x-appwrite": { "method": "updateMfaChallenge", - "weight": 53, + "weight": 54, "cookies": false, "type": "", "deprecated": false, @@ -894,9 +858,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -958,7 +919,7 @@ }, "x-appwrite": { "method": "listMfaFactors", - "weight": 45, + "weight": 46, "cookies": false, "type": "", "deprecated": false, @@ -973,9 +934,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1012,7 +970,7 @@ }, "x-appwrite": { "method": "getMfaRecoveryCodes", - "weight": 50, + "weight": 51, "cookies": false, "type": "", "deprecated": false, @@ -1027,9 +985,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1064,7 +1019,7 @@ }, "x-appwrite": { "method": "createMfaRecoveryCodes", - "weight": 48, + "weight": 49, "cookies": false, "type": "", "deprecated": false, @@ -1079,9 +1034,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1116,7 +1068,7 @@ }, "x-appwrite": { "method": "updateMfaRecoveryCodes", - "weight": 49, + "weight": 50, "cookies": false, "type": "", "deprecated": false, @@ -1131,9 +1083,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1170,7 +1119,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 32, + "weight": 33, "cookies": false, "type": "", "deprecated": false, @@ -1185,9 +1134,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1243,7 +1189,7 @@ }, "x-appwrite": { "method": "updatePassword", - "weight": 33, + "weight": 34, "cookies": false, "type": "", "deprecated": false, @@ -1258,9 +1204,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1321,7 +1264,7 @@ }, "x-appwrite": { "method": "updatePhone", - "weight": 35, + "weight": 36, "cookies": false, "type": "", "deprecated": false, @@ -1336,9 +1279,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1400,7 +1340,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 30, + "weight": 31, "cookies": false, "type": "", "deprecated": false, @@ -1415,9 +1355,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1452,7 +1389,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 36, + "weight": 37, "cookies": false, "type": "", "deprecated": false, @@ -1467,9 +1404,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1525,7 +1459,7 @@ }, "x-appwrite": { "method": "createRecovery", - "weight": 38, + "weight": 39, "cookies": false, "type": "", "deprecated": false, @@ -1543,9 +1477,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1605,7 +1536,7 @@ }, "x-appwrite": { "method": "updateRecovery", - "weight": 39, + "weight": 40, "cookies": false, "type": "", "deprecated": false, @@ -1620,9 +1551,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1690,7 +1618,7 @@ }, "x-appwrite": { "method": "listSessions", - "weight": 11, + "weight": 12, "cookies": false, "type": "", "deprecated": false, @@ -1705,9 +1633,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1735,7 +1660,7 @@ }, "x-appwrite": { "method": "deleteSessions", - "weight": 12, + "weight": 13, "cookies": false, "type": "", "deprecated": false, @@ -1750,9 +1675,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1789,7 +1711,7 @@ }, "x-appwrite": { "method": "createAnonymousSession", - "weight": 17, + "weight": 18, "cookies": false, "type": "", "deprecated": false, @@ -1804,9 +1726,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1840,7 +1759,7 @@ }, "x-appwrite": { "method": "createEmailPasswordSession", - "weight": 16, + "weight": 17, "cookies": false, "type": "", "deprecated": false, @@ -1855,9 +1774,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1916,7 +1832,7 @@ }, "x-appwrite": { "method": "updateMagicURLSession", - "weight": 26, + "weight": 27, "cookies": false, "type": "", "deprecated": true, @@ -1931,9 +1847,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1992,7 +1905,7 @@ }, "x-appwrite": { "method": "updatePhoneSession", - "weight": 27, + "weight": 28, "cookies": false, "type": "", "deprecated": true, @@ -2007,9 +1920,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2068,7 +1978,7 @@ }, "x-appwrite": { "method": "createSession", - "weight": 18, + "weight": 19, "cookies": false, "type": "", "deprecated": false, @@ -2083,9 +1993,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2144,7 +2051,7 @@ }, "x-appwrite": { "method": "getSession", - "weight": 13, + "weight": 14, "cookies": false, "type": "", "deprecated": false, @@ -2159,9 +2066,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2208,7 +2112,7 @@ }, "x-appwrite": { "method": "updateSession", - "weight": 15, + "weight": 16, "cookies": false, "type": "", "deprecated": false, @@ -2223,9 +2127,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2265,7 +2166,7 @@ }, "x-appwrite": { "method": "deleteSession", - "weight": 14, + "weight": 15, "cookies": false, "type": "", "deprecated": false, @@ -2280,9 +2181,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2331,7 +2229,7 @@ }, "x-appwrite": { "method": "updateStatus", - "weight": 37, + "weight": 38, "cookies": false, "type": "", "deprecated": false, @@ -2346,9 +2244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2385,7 +2280,7 @@ }, "x-appwrite": { "method": "createEmailToken", - "weight": 25, + "weight": 26, "cookies": false, "type": "", "deprecated": false, @@ -2400,9 +2295,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2451,7 +2343,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2466,7 +2358,7 @@ }, "x-appwrite": { "method": "createMagicURLToken", - "weight": 24, + "weight": 25, "cookies": false, "type": "", "deprecated": false, @@ -2484,9 +2376,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2548,7 +2437,7 @@ }, "x-appwrite": { "method": "createOAuth2Token", - "weight": 23, + "weight": 24, "cookies": false, "type": "webAuth", "deprecated": false, @@ -2563,9 +2452,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2691,7 +2577,7 @@ }, "x-appwrite": { "method": "createPhoneToken", - "weight": 28, + "weight": 29, "cookies": false, "type": "", "deprecated": false, @@ -2709,9 +2595,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2770,7 +2653,7 @@ }, "x-appwrite": { "method": "createVerification", - "weight": 40, + "weight": 41, "cookies": false, "type": "", "deprecated": false, @@ -2785,9 +2668,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2841,7 +2721,7 @@ }, "x-appwrite": { "method": "updateVerification", - "weight": 41, + "weight": 42, "cookies": false, "type": "", "deprecated": false, @@ -2856,9 +2736,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2920,7 +2797,7 @@ }, "x-appwrite": { "method": "createPhoneVerification", - "weight": 42, + "weight": 43, "cookies": false, "type": "", "deprecated": false, @@ -2938,9 +2815,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2975,7 +2849,7 @@ }, "x-appwrite": { "method": "updatePhoneVerification", - "weight": 43, + "weight": 44, "cookies": false, "type": "", "deprecated": false, @@ -2990,9 +2864,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3047,7 +2918,7 @@ }, "x-appwrite": { "method": "getBrowser", - "weight": 60, + "weight": 61, "cookies": false, "type": "location", "deprecated": false, @@ -3063,9 +2934,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3177,7 +3045,7 @@ }, "x-appwrite": { "method": "getCreditCard", - "weight": 59, + "weight": 60, "cookies": false, "type": "location", "deprecated": false, @@ -3193,9 +3061,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3212,7 +3077,7 @@ "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.", + "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", @@ -3233,7 +3098,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3252,7 +3118,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ] }, "in": "path" @@ -3311,7 +3178,7 @@ }, "x-appwrite": { "method": "getFavicon", - "weight": 63, + "weight": 64, "cookies": false, "type": "location", "deprecated": false, @@ -3327,9 +3194,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3373,7 +3237,7 @@ }, "x-appwrite": { "method": "getFlag", - "weight": 61, + "weight": 62, "cookies": false, "type": "location", "deprecated": false, @@ -3389,9 +3253,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3865,7 +3726,7 @@ }, "x-appwrite": { "method": "getImage", - "weight": 62, + "weight": 63, "cookies": false, "type": "location", "deprecated": false, @@ -3881,9 +3742,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3951,7 +3809,7 @@ }, "x-appwrite": { "method": "getInitials", - "weight": 65, + "weight": 66, "cookies": false, "type": "location", "deprecated": false, @@ -3967,9 +3825,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4047,7 +3902,7 @@ }, "x-appwrite": { "method": "getQR", - "weight": 64, + "weight": 65, "cookies": false, "type": "location", "deprecated": false, @@ -4063,9 +3918,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4150,7 +4002,7 @@ }, "x-appwrite": { "method": "list", - "weight": 70, + "weight": 71, "cookies": false, "type": "", "deprecated": false, @@ -4164,9 +4016,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4226,7 +4075,7 @@ }, "x-appwrite": { "method": "create", - "weight": 69, + "weight": 70, "cookies": false, "type": "", "deprecated": false, @@ -4240,9 +4089,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4308,7 +4154,7 @@ }, "x-appwrite": { "method": "get", - "weight": 71, + "weight": 72, "cookies": false, "type": "", "deprecated": false, @@ -4322,9 +4168,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4370,7 +4213,7 @@ }, "x-appwrite": { "method": "update", - "weight": 73, + "weight": 74, "cookies": false, "type": "", "deprecated": false, @@ -4384,9 +4227,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4449,7 +4289,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 74, + "weight": 75, "cookies": false, "type": "", "deprecated": false, @@ -4463,9 +4303,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4513,7 +4350,7 @@ }, "x-appwrite": { "method": "listCollections", - "weight": 76, + "weight": 77, "cookies": false, "type": "", "deprecated": false, @@ -4527,9 +4364,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4599,7 +4433,7 @@ }, "x-appwrite": { "method": "createCollection", - "weight": 75, + "weight": 76, "cookies": false, "type": "", "deprecated": false, @@ -4613,9 +4447,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4706,7 +4537,7 @@ }, "x-appwrite": { "method": "getCollection", - "weight": 77, + "weight": 78, "cookies": false, "type": "", "deprecated": false, @@ -4720,9 +4551,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4778,7 +4606,7 @@ }, "x-appwrite": { "method": "updateCollection", - "weight": 79, + "weight": 80, "cookies": false, "type": "", "deprecated": false, @@ -4792,9 +4620,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4880,7 +4705,7 @@ }, "x-appwrite": { "method": "deleteCollection", - "weight": 80, + "weight": 81, "cookies": false, "type": "", "deprecated": false, @@ -4894,9 +4719,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4954,7 +4776,7 @@ }, "x-appwrite": { "method": "listAttributes", - "weight": 91, + "weight": 92, "cookies": false, "type": "", "deprecated": false, @@ -4968,9 +4790,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5041,7 +4860,7 @@ }, "x-appwrite": { "method": "createBooleanAttribute", - "weight": 88, + "weight": 89, "cookies": false, "type": "", "deprecated": false, @@ -5055,9 +4874,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5140,7 +4956,7 @@ "200": { "description": "AttributeBoolean", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeBoolean" } @@ -5150,7 +4966,7 @@ }, "x-appwrite": { "method": "updateBooleanAttribute", - "weight": 100, + "weight": 101, "cookies": false, "type": "", "deprecated": false, @@ -5164,9 +4980,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5264,7 +5077,7 @@ }, "x-appwrite": { "method": "createDatetimeAttribute", - "weight": 89, + "weight": 90, "cookies": false, "type": "", "deprecated": false, @@ -5278,9 +5091,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5363,7 +5173,7 @@ "200": { "description": "AttributeDatetime", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeDatetime" } @@ -5373,7 +5183,7 @@ }, "x-appwrite": { "method": "updateDatetimeAttribute", - "weight": 101, + "weight": 102, "cookies": false, "type": "", "deprecated": false, @@ -5387,9 +5197,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5487,7 +5294,7 @@ }, "x-appwrite": { "method": "createEmailAttribute", - "weight": 82, + "weight": 83, "cookies": false, "type": "", "deprecated": false, @@ -5501,9 +5308,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5586,7 +5390,7 @@ "200": { "description": "AttributeEmail", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEmail" } @@ -5596,7 +5400,7 @@ }, "x-appwrite": { "method": "updateEmailAttribute", - "weight": 94, + "weight": 95, "cookies": false, "type": "", "deprecated": false, @@ -5610,9 +5414,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5710,7 +5511,7 @@ }, "x-appwrite": { "method": "createEnumAttribute", - "weight": 83, + "weight": 84, "cookies": false, "type": "", "deprecated": false, @@ -5724,9 +5525,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5818,7 +5616,7 @@ "200": { "description": "AttributeEnum", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeEnum" } @@ -5828,7 +5626,7 @@ }, "x-appwrite": { "method": "updateEnumAttribute", - "weight": 95, + "weight": 96, "cookies": false, "type": "", "deprecated": false, @@ -5842,9 +5640,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5951,7 +5746,7 @@ }, "x-appwrite": { "method": "createFloatAttribute", - "weight": 87, + "weight": 88, "cookies": false, "type": "", "deprecated": false, @@ -5965,9 +5760,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6060,7 +5852,7 @@ "200": { "description": "AttributeFloat", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeFloat" } @@ -6070,7 +5862,7 @@ }, "x-appwrite": { "method": "updateFloatAttribute", - "weight": 99, + "weight": 100, "cookies": false, "type": "", "deprecated": false, @@ -6084,9 +5876,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6164,8 +5953,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6196,7 +5983,7 @@ }, "x-appwrite": { "method": "createIntegerAttribute", - "weight": 86, + "weight": 87, "cookies": false, "type": "", "deprecated": false, @@ -6210,9 +5997,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6305,7 +6089,7 @@ "200": { "description": "AttributeInteger", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeInteger" } @@ -6315,7 +6099,7 @@ }, "x-appwrite": { "method": "updateIntegerAttribute", - "weight": 98, + "weight": 99, "cookies": false, "type": "", "deprecated": false, @@ -6329,9 +6113,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6409,8 +6190,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6441,7 +6220,7 @@ }, "x-appwrite": { "method": "createIpAttribute", - "weight": 84, + "weight": 85, "cookies": false, "type": "", "deprecated": false, @@ -6455,9 +6234,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6540,7 +6316,7 @@ "200": { "description": "AttributeIP", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeIp" } @@ -6550,7 +6326,7 @@ }, "x-appwrite": { "method": "updateIpAttribute", - "weight": 96, + "weight": 97, "cookies": false, "type": "", "deprecated": false, @@ -6564,9 +6340,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6664,7 +6437,7 @@ }, "x-appwrite": { "method": "createRelationshipAttribute", - "weight": 90, + "weight": 91, "cookies": false, "type": "", "deprecated": false, @@ -6678,9 +6451,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6798,7 +6568,7 @@ }, "x-appwrite": { "method": "createStringAttribute", - "weight": 81, + "weight": 82, "cookies": false, "type": "", "deprecated": false, @@ -6812,9 +6582,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6908,7 +6675,7 @@ "200": { "description": "AttributeString", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeString" } @@ -6918,7 +6685,7 @@ }, "x-appwrite": { "method": "updateStringAttribute", - "weight": 93, + "weight": 94, "cookies": false, "type": "", "deprecated": false, @@ -6932,9 +6699,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7037,7 +6801,7 @@ }, "x-appwrite": { "method": "createUrlAttribute", - "weight": 85, + "weight": 86, "cookies": false, "type": "", "deprecated": false, @@ -7051,9 +6815,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7136,7 +6897,7 @@ "200": { "description": "AttributeURL", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeUrl" } @@ -7146,7 +6907,7 @@ }, "x-appwrite": { "method": "updateUrlAttribute", - "weight": 97, + "weight": 98, "cookies": false, "type": "", "deprecated": false, @@ -7160,9 +6921,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7291,7 +7049,7 @@ }, "x-appwrite": { "method": "getAttribute", - "weight": 92, + "weight": 93, "cookies": false, "type": "", "deprecated": false, @@ -7305,9 +7063,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7365,7 +7120,7 @@ }, "x-appwrite": { "method": "deleteAttribute", - "weight": 103, + "weight": 104, "cookies": false, "type": "", "deprecated": false, @@ -7379,9 +7134,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7438,7 +7190,7 @@ "200": { "description": "AttributeRelationship", "content": { - "": { + "application\/json": { "schema": { "$ref": "#\/components\/schemas\/attributeRelationship" } @@ -7448,7 +7200,7 @@ }, "x-appwrite": { "method": "updateRelationshipAttribute", - "weight": 102, + "weight": 103, "cookies": false, "type": "", "deprecated": false, @@ -7462,9 +7214,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7559,7 +7308,7 @@ }, "x-appwrite": { "method": "listDocuments", - "weight": 109, + "weight": 110, "cookies": false, "type": "", "deprecated": false, @@ -7575,9 +7324,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7633,7 +7379,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -7648,7 +7394,7 @@ }, "x-appwrite": { "method": "createDocument", - "weight": 108, + "weight": 109, "cookies": false, "type": "", "deprecated": false, @@ -7664,9 +7410,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7759,7 +7502,7 @@ }, "x-appwrite": { "method": "getDocument", - "weight": 110, + "weight": 111, "cookies": false, "type": "", "deprecated": false, @@ -7775,9 +7518,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7858,7 +7598,7 @@ }, "x-appwrite": { "method": "updateDocument", - "weight": 112, + "weight": 113, "cookies": false, "type": "", "deprecated": false, @@ -7874,9 +7614,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7961,7 +7698,7 @@ }, "x-appwrite": { "method": "deleteDocument", - "weight": 113, + "weight": 114, "cookies": false, "type": "", "deprecated": false, @@ -7977,9 +7714,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8049,7 +7783,7 @@ }, "x-appwrite": { "method": "listIndexes", - "weight": 105, + "weight": 106, "cookies": false, "type": "", "deprecated": false, @@ -8063,9 +7797,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8134,7 +7865,7 @@ }, "x-appwrite": { "method": "createIndex", - "weight": 104, + "weight": 105, "cookies": false, "type": "", "deprecated": false, @@ -8148,9 +7879,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8257,7 +7985,7 @@ }, "x-appwrite": { "method": "getIndex", - "weight": 106, + "weight": 107, "cookies": false, "type": "", "deprecated": false, @@ -8271,9 +7999,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8331,7 +8056,7 @@ }, "x-appwrite": { "method": "deleteIndex", - "weight": 107, + "weight": 108, "cookies": false, "type": "", "deprecated": false, @@ -8345,9 +8070,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8414,12 +8136,12 @@ }, "x-appwrite": { "method": "list", - "weight": 289, + "weight": 368, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/list-functions.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}", @@ -8428,9 +8150,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8445,7 +8164,7 @@ "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, deployment, schedule, scheduleNext, schedulePrevious, timeout, entrypoint, commands, installationId", + "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", @@ -8490,12 +8209,12 @@ }, "x-appwrite": { "method": "create", - "weight": 288, + "weight": 365, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-function.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}", @@ -8504,9 +8223,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8560,6 +8276,7 @@ "python-3.11", "python-3.12", "python-ml-3.11", + "python-ml-3.12", "deno-1.21", "deno-1.24", "deno-1.35", @@ -8570,6 +8287,7 @@ "dart-2.16", "dart-2.17", "dart-2.18", + "dart-2.19", "dart-3.0", "dart-3.1", "dart-3.3", @@ -8596,7 +8314,10 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29" ], "x-enum-name": null, "x-enum-keys": [] @@ -8634,7 +8355,7 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "x-example": false }, "entrypoint": { @@ -8680,26 +8401,6 @@ "description": "Path to function code in the linked repo.", "x-example": "<PROVIDER_ROOT_DIRECTORY>" }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "x-example": "<TEMPLATE_REPOSITORY>" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "x-example": "<TEMPLATE_OWNER>" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "x-example": "<TEMPLATE_ROOT_DIRECTORY>" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "x-example": "<TEMPLATE_VERSION>" - }, "specification": { "type": "string", "description": "Runtime specification for the function and builds.", @@ -8739,23 +8440,20 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 290, + "weight": 370, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-runtimes.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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": "functions.read", + "scope": "public", "platforms": [ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8771,12 +8469,12 @@ }, "\/functions\/specifications": { "get": { - "summary": "List available function runtime specifications", + "summary": "List specifications", "operationId": "functionsListSpecifications", "tags": [ "functions" ], - "description": "List allowed function specifications for this instance.\n", + "description": "List allowed function specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -8791,12 +8489,12 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 291, + "weight": 371, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-specifications.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -8806,9 +8504,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8844,12 +8539,12 @@ }, "x-appwrite": { "method": "get", - "weight": 292, + "weight": 366, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-function.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}", @@ -8858,9 +8553,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8906,12 +8598,12 @@ }, "x-appwrite": { "method": "update", - "weight": 295, + "weight": 367, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/update.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-function.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}", @@ -8920,9 +8612,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8983,6 +8672,7 @@ "python-3.11", "python-3.12", "python-ml-3.11", + "python-ml-3.12", "deno-1.21", "deno-1.24", "deno-1.35", @@ -8993,6 +8683,7 @@ "dart-2.16", "dart-2.17", "dart-2.18", + "dart-2.19", "dart-3.0", "dart-3.1", "dart-3.3", @@ -9019,7 +8710,10 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29" ], "x-enum-name": null, "x-enum-keys": [] @@ -9057,7 +8751,7 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "x-example": false }, "entrypoint": { @@ -9132,12 +8826,12 @@ }, "x-appwrite": { "method": "delete", - "weight": 298, + "weight": 369, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/delete-function.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}", @@ -9146,9 +8840,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9174,6 +8865,86 @@ ] } }, + "\/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", + "weight": 374, + "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", @@ -9181,7 +8952,7 @@ "tags": [ "functions" ], - "description": "Get a list of all the project's code deployments. You can use the query params to filter your results.", + "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", @@ -9196,12 +8967,12 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 300, + "weight": 375, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-deployments.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9210,9 +8981,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9237,7 +9005,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: size, buildId, activate, entrypoint, commands, type, size", + "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", @@ -9282,12 +9050,12 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 299, + "weight": 372, "cookies": false, "type": "upload", "deprecated": false, "demo": "functions\/create-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9296,9 +9064,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9359,16 +9124,16 @@ } } }, - "\/functions\/{functionId}\/deployments\/{deploymentId}": { - "get": { - "summary": "Get deployment", - "operationId": "functionsGetDeployment", + "\/functions\/{functionId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "functionsCreateDuplicateDeployment", "tags": [ "functions" ], - "description": "Get a code deployment by its unique ID.", + "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": { - "200": { + "202": { "description": "Deployment", "content": { "application\/json": { @@ -9380,24 +9145,21 @@ } }, "x-appwrite": { - "method": "getDeployment", - "weight": 301, + "method": "createDuplicateDeployment", + "weight": 380, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/get-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-deployment.md", + "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.read", + "scope": "functions.write", "platforms": [ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9419,46 +9181,62 @@ "x-example": "<FUNCTION_ID>" }, "in": "path" - }, - { - "name": "deploymentId", - "description": "Deployment ID.", - "required": true, - "schema": { - "type": "string", - "x-example": "<DEPLOYMENT_ID>" - }, - "in": "path" } - ] - }, - "patch": { - "summary": "Update deployment", - "operationId": "functionsUpdateDeployment", + ], + "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": "Update the function code deployment ID using the unique function ID. Use this endpoint to switch the code deployment that should be executed by the execution endpoint.", + "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": { - "200": { - "description": "Function", + "202": { + "description": "Deployment", "content": { "application\/json": { "schema": { - "$ref": "#\/components\/schemas\/function" + "$ref": "#\/components\/schemas\/deployment" } } } } }, "x-appwrite": { - "method": "updateDeployment", - "weight": 297, + "method": "createTemplateDeployment", + "weight": 377, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/update-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-function-deployment.md", + "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}", @@ -9467,9 +9245,206 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", + "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", + "weight": 378, + "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", + "weight": 373, + "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": [] @@ -9518,12 +9493,12 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 302, + "weight": 376, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9532,164 +9507,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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}\/build": { - "post": { - "summary": "Rebuild deployment", - "operationId": "functionsCreateBuild", - "tags": [ - "functions" - ], - "description": "", - "responses": { - "204": { - "description": "No content" - } - }, - "x-appwrite": { - "method": "createBuild", - "weight": 303, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "functions.write", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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" - } - ], - "requestBody": { - "content": { - "application\/json": { - "schema": { - "type": "object", - "properties": { - "buildId": { - "type": "string", - "description": "Build unique ID.", - "x-example": "<BUILD_ID>" - } - } - } - } - } - } - }, - "patch": { - "summary": "Cancel deployment", - "operationId": "functionsUpdateDeploymentBuild", - "tags": [ - "functions" - ], - "description": "", - "responses": { - "200": { - "description": "Build", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/build" - } - } - } - } - }, - "x-appwrite": { - "method": "updateDeploymentBuild", - "weight": 304, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "functions.write", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9732,7 +9549,7 @@ "tags": [ "functions" ], - "description": "Get a Deployment's contents by its unique ID. This endpoint supports range requests for partial or streaming file download.", + "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" @@ -9740,12 +9557,12 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 296, + "weight": 379, "cookies": false, "type": "location", "deprecated": false, "demo": "functions\/get-deployment-download.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9755,9 +9572,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9770,6 +9584,94 @@ "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", + "weight": 381, + "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", @@ -9816,12 +9718,12 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 306, + "weight": 384, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-executions.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9832,9 +9734,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -9871,17 +9770,6 @@ "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" } ] }, @@ -9906,12 +9794,12 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 305, + "weight": 382, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9922,9 +9810,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10025,12 +9910,12 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 307, + "weight": 383, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10041,9 +9926,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10086,7 +9968,7 @@ "tags": [ "functions" ], - "description": "Delete a function execution by its unique ID.\n", + "description": "Delete a function execution by its unique ID.", "responses": { "204": { "description": "No content" @@ -10094,12 +9976,12 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 308, + "weight": 385, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10108,9 +9990,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10168,12 +10047,12 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 310, + "weight": 390, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-variables.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10182,9 +10061,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10230,12 +10106,12 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 309, + "weight": 388, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10244,9 +10120,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10285,6 +10158,11 @@ "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": [ @@ -10319,12 +10197,12 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 311, + "weight": 389, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10333,9 +10211,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10391,12 +10266,12 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 312, + "weight": 391, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/update-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10405,9 +10280,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10456,6 +10328,11 @@ "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": [ @@ -10480,12 +10357,12 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 313, + "weight": 392, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10494,9 +10371,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10554,7 +10428,7 @@ }, "x-appwrite": { "method": "query", - "weight": 331, + "weight": 303, "cookies": false, "type": "graphql", "deprecated": false, @@ -10570,9 +10444,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10610,7 +10481,7 @@ }, "x-appwrite": { "method": "mutation", - "weight": 330, + "weight": 302, "cookies": false, "type": "graphql", "deprecated": false, @@ -10626,9 +10497,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10666,7 +10534,7 @@ }, "x-appwrite": { "method": "get", - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -10680,9 +10548,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10718,7 +10583,7 @@ }, "x-appwrite": { "method": "getAntivirus", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -10732,9 +10597,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10770,7 +10632,7 @@ }, "x-appwrite": { "method": "getCache", - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -10784,9 +10646,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10836,9 +10695,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10885,7 +10741,7 @@ }, "x-appwrite": { "method": "getDB", - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -10899,9 +10755,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10951,61 +10804,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [], - "Key": [] - } - }, - "security": [ - { - "Project": [], - "Key": [] - } - ] - } - }, - "\/health\/queue": { - "get": { - "summary": "Get queue", - "operationId": "healthGetQueue", - "tags": [ - "health" - ], - "description": "Check the Appwrite queue messaging servers are up and connection is successful.", - "responses": { - "200": { - "description": "Health Status", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/healthStatus" - } - } - } - } - }, - "x-appwrite": { - "method": "getQueue", - "weight": 129, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "health\/get-queue.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "health.read", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11055,9 +10853,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11120,9 +10915,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11185,9 +10977,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11261,9 +11050,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11312,7 +11098,7 @@ }, "x-appwrite": { "method": "getFailedJobs", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -11326,9 +11112,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11354,8 +11137,9 @@ "v1-audits", "v1-mails", "v1-functions", - "v1-usage", - "v1-usage-dump", + "v1-stats-resources", + "v1-stats-usage", + "v1-stats-usage-dump", "v1-webhooks", "v1-certificates", "v1-builds", @@ -11417,9 +11201,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11482,9 +11263,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11547,9 +11325,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11612,9 +11387,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11677,9 +11449,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11706,9 +11475,71 @@ ] } }, - "\/health\/queue\/usage": { + "\/health\/queue\/stats-resources": { "get": { - "summary": "Get usage queue", + "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", + "weight": 143, + "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" @@ -11728,12 +11559,12 @@ }, "x-appwrite": { "method": "getQueueUsage", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, "demo": "health\/get-queue-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11742,9 +11573,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11771,10 +11599,10 @@ ] } }, - "\/health\/queue\/usage-dump": { + "\/health\/queue\/stats-usage-dump": { "get": { "summary": "Get usage dump queue", - "operationId": "healthGetQueueUsageDump", + "operationId": "healthGetQueueStatsUsageDump", "tags": [ "health" ], @@ -11792,13 +11620,13 @@ } }, "x-appwrite": { - "method": "getQueueUsageDump", - "weight": 144, + "method": "getQueueStatsUsageDump", + "weight": 145, "cookies": false, "type": "", "deprecated": false, - "demo": "health\/get-queue-usage-dump.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-usage-dump.md", + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -11807,9 +11635,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11872,9 +11697,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11923,7 +11745,7 @@ }, "x-appwrite": { "method": "getStorage", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -11937,9 +11759,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11975,7 +11794,7 @@ }, "x-appwrite": { "method": "getStorageLocal", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -11989,9 +11808,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12041,9 +11857,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12079,7 +11892,7 @@ }, "x-appwrite": { "method": "get", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -12095,9 +11908,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12135,7 +11945,7 @@ }, "x-appwrite": { "method": "listCodes", - "weight": 118, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -12151,9 +11961,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12191,7 +11998,7 @@ }, "x-appwrite": { "method": "listContinents", - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -12207,9 +12014,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12247,7 +12051,7 @@ }, "x-appwrite": { "method": "listCountries", - "weight": 119, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -12263,9 +12067,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12303,7 +12104,7 @@ }, "x-appwrite": { "method": "listCountriesEU", - "weight": 120, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -12319,9 +12120,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12359,7 +12157,7 @@ }, "x-appwrite": { "method": "listCountriesPhones", - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -12375,9 +12173,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [], "Session": [] @@ -12415,7 +12210,7 @@ }, "x-appwrite": { "method": "listCurrencies", - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -12431,9 +12226,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12471,7 +12263,7 @@ }, "x-appwrite": { "method": "listLanguages", - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -12487,9 +12279,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12527,7 +12316,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -12542,9 +12331,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12606,7 +12392,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -12621,9 +12407,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12738,7 +12521,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -12753,7 +12536,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -12768,9 +12551,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12902,7 +12682,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -12917,9 +12697,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12978,7 +12755,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "x-example": "{}" }, "action": { @@ -12998,7 +12775,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "x-example": "<SOUND>" }, "color": { @@ -13012,9 +12789,9 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "x-example": null }, "draft": { "type": "boolean", @@ -13025,12 +12802,31 @@ "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", - "title", - "body" + "messageId" ] } } @@ -13045,7 +12841,7 @@ "tags": [ "messaging" ], - "description": "Update a push notification by its unique ID.\n", + "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", @@ -13060,7 +12856,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -13075,9 +12871,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13190,6 +12983,27 @@ "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": [] } } } @@ -13220,7 +13034,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -13235,9 +13049,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13317,7 +13128,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -13332,12 +13143,12 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 362, "cookies": false, "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.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}", @@ -13347,9 +13158,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13447,7 +13255,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -13462,9 +13270,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13503,7 +13308,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -13518,9 +13323,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13568,7 +13370,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -13583,9 +13385,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13646,7 +13445,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -13661,9 +13460,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13724,7 +13520,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -13739,9 +13535,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13803,7 +13596,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -13818,9 +13611,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13911,7 +13701,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -13926,9 +13716,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14022,7 +13809,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -14037,9 +13824,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14110,7 +13894,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -14125,9 +13909,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14201,7 +13982,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -14216,9 +13997,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14319,7 +14097,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -14334,9 +14112,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14440,7 +14215,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -14455,9 +14230,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14538,7 +14310,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -14553,9 +14325,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14639,7 +14408,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -14654,9 +14423,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14747,7 +14513,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -14762,9 +14528,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14858,7 +14621,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -14873,9 +14636,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15004,7 +14764,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -15019,9 +14779,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15152,7 +14909,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -15167,9 +14924,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15250,7 +15004,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -15265,9 +15019,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15351,7 +15102,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -15366,9 +15117,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15449,7 +15197,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -15464,9 +15212,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15550,7 +15295,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -15565,9 +15310,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15648,7 +15390,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -15663,9 +15405,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15749,7 +15488,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -15764,9 +15503,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15847,7 +15583,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -15862,9 +15598,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15948,7 +15681,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -15963,9 +15696,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16004,7 +15734,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -16019,9 +15749,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16069,7 +15796,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -16084,9 +15811,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16147,7 +15871,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16162,9 +15886,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16225,7 +15946,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -16240,9 +15961,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16302,7 +16020,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -16317,9 +16035,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16388,7 +16103,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -16403,9 +16118,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16451,7 +16163,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16466,9 +16178,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16531,7 +16240,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16546,9 +16255,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16596,7 +16302,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -16611,9 +16317,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16674,7 +16377,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16689,9 +16392,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16761,7 +16461,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -16778,9 +16478,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -16855,7 +16552,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -16870,9 +16567,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16921,7 +16615,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16938,9 +16632,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -16978,6 +16669,2200 @@ ] } }, + "\/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", + "weight": 397, + "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", + "weight": 395, + "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", + "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", + "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" + ], + "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", + "weight": 400, + "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", + "weight": 423, + "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", + "weight": 396, + "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", + "weight": 398, + "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", + "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", + "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" + ], + "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", + "weight": 399, + "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", + "weight": 406, + "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", + "weight": 405, + "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", + "weight": 401, + "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", + "weight": 409, + "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", + "weight": 402, + "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", + "weight": 403, + "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", + "weight": 404, + "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", + "weight": 407, + "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": "Download deployment", + "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", + "weight": 408, + "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", + "weight": 410, + "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", + "weight": 412, + "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", + "weight": 411, + "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", + "weight": 413, + "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", + "weight": 416, + "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", + "weight": 414, + "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", + "weight": 415, + "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", + "weight": 417, + "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", + "weight": 418, + "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", @@ -17000,7 +18885,7 @@ }, "x-appwrite": { "method": "listBuckets", - "weight": 203, + "weight": 204, "cookies": false, "type": "", "deprecated": false, @@ -17014,9 +18899,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17076,7 +18958,7 @@ }, "x-appwrite": { "method": "createBucket", - "weight": 202, + "weight": 203, "cookies": false, "type": "", "deprecated": false, @@ -17090,9 +18972,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17206,7 +19085,7 @@ }, "x-appwrite": { "method": "getBucket", - "weight": 204, + "weight": 205, "cookies": false, "type": "", "deprecated": false, @@ -17220,9 +19099,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17268,7 +19144,7 @@ }, "x-appwrite": { "method": "updateBucket", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -17282,9 +19158,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17395,7 +19268,7 @@ }, "x-appwrite": { "method": "deleteBucket", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -17409,9 +19282,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17459,7 +19329,7 @@ }, "x-appwrite": { "method": "listFiles", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -17475,9 +19345,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17549,7 +19416,7 @@ }, "x-appwrite": { "method": "createFile", - "weight": 207, + "weight": 208, "cookies": false, "type": "upload", "deprecated": false, @@ -17565,9 +19432,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17651,7 +19515,7 @@ }, "x-appwrite": { "method": "getFile", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -17667,9 +19531,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17727,7 +19588,7 @@ }, "x-appwrite": { "method": "updateFile", - "weight": 214, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -17743,9 +19604,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17820,7 +19678,7 @@ }, "x-appwrite": { "method": "deleteFile", - "weight": 215, + "weight": 216, "cookies": false, "type": "", "deprecated": false, @@ -17836,9 +19694,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17891,7 +19746,7 @@ }, "x-appwrite": { "method": "getFileDownload", - "weight": 211, + "weight": 212, "cookies": false, "type": "location", "deprecated": false, @@ -17907,9 +19762,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -17962,7 +19814,7 @@ }, "x-appwrite": { "method": "getFilePreview", - "weight": 210, + "weight": 211, "cookies": false, "type": "location", "deprecated": false, @@ -17978,9 +19830,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18156,6 +20005,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -18182,7 +20032,7 @@ }, "x-appwrite": { "method": "getFileView", - "weight": 212, + "weight": 213, "cookies": false, "type": "location", "deprecated": false, @@ -18198,9 +20048,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18260,7 +20107,7 @@ }, "x-appwrite": { "method": "list", - "weight": 219, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -18276,9 +20123,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18340,7 +20184,7 @@ }, "x-appwrite": { "method": "create", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -18356,9 +20200,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18429,7 +20270,7 @@ }, "x-appwrite": { "method": "get", - "weight": 220, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -18445,9 +20286,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18495,7 +20333,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -18511,9 +20349,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18573,7 +20408,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -18589,9 +20424,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18641,7 +20473,7 @@ }, "x-appwrite": { "method": "listMemberships", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -18657,9 +20489,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18686,7 +20515,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: userId, teamId, invited, joined, confirm", + "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", @@ -18731,7 +20560,7 @@ }, "x-appwrite": { "method": "createMembership", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -18747,9 +20576,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18846,7 +20672,7 @@ }, "x-appwrite": { "method": "getMembership", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -18862,9 +20688,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18922,7 +20745,7 @@ }, "x-appwrite": { "method": "updateMembership", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -18938,9 +20761,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19013,7 +20833,7 @@ }, "x-appwrite": { "method": "deleteMembership", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -19029,9 +20849,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19091,7 +20908,7 @@ }, "x-appwrite": { "method": "updateMembershipStatus", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -19106,9 +20923,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19192,7 +21006,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -19207,9 +21021,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19256,7 +21067,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -19271,9 +21082,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19341,7 +21149,7 @@ }, "x-appwrite": { "method": "list", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -19355,9 +21163,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19417,7 +21222,7 @@ }, "x-appwrite": { "method": "create", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -19431,9 +21236,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19508,7 +21310,7 @@ }, "x-appwrite": { "method": "createArgon2User", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -19522,9 +21324,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19596,7 +21395,7 @@ }, "x-appwrite": { "method": "createBcryptUser", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -19610,9 +21409,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19684,7 +21480,7 @@ }, "x-appwrite": { "method": "listIdentities", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -19698,9 +21494,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19755,7 +21548,7 @@ }, "x-appwrite": { "method": "deleteIdentity", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -19769,9 +21562,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19819,7 +21609,7 @@ }, "x-appwrite": { "method": "createMD5User", - "weight": 234, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -19833,9 +21623,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19907,7 +21694,7 @@ }, "x-appwrite": { "method": "createPHPassUser", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -19921,9 +21708,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19995,7 +21779,7 @@ }, "x-appwrite": { "method": "createScryptUser", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -20009,9 +21793,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20113,7 +21894,7 @@ }, "x-appwrite": { "method": "createScryptModifiedUser", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -20127,9 +21908,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20219,7 +21997,7 @@ }, "x-appwrite": { "method": "createSHAUser", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -20233,9 +22011,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20327,7 +22102,7 @@ }, "x-appwrite": { "method": "get", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -20341,9 +22116,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20382,7 +22154,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -20396,9 +22168,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20446,7 +22215,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -20460,9 +22229,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20529,7 +22295,7 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -20543,9 +22309,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20614,7 +22377,7 @@ }, "x-appwrite": { "method": "updateLabels", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -20628,9 +22391,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20700,7 +22460,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -20714,9 +22474,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20777,7 +22534,7 @@ }, "x-appwrite": { "method": "listMemberships", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -20791,9 +22548,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20815,6 +22569,30 @@ "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" } ] } @@ -20841,7 +22619,7 @@ }, "x-appwrite": { "method": "updateMfa", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -20855,9 +22633,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20911,20 +22686,13 @@ ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "content": { - "application\/json": { - "schema": { - "$ref": "#\/components\/schemas\/user" - } - } - } + "204": { + "description": "No content" } }, "x-appwrite": { "method": "deleteMfaAuthenticator", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -20938,9 +22706,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21003,7 +22768,7 @@ }, "x-appwrite": { "method": "listMfaFactors", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -21017,9 +22782,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21067,7 +22829,7 @@ }, "x-appwrite": { "method": "getMfaRecoveryCodes", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -21081,9 +22843,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21129,7 +22888,7 @@ }, "x-appwrite": { "method": "updateMfaRecoveryCodes", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -21143,9 +22902,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21191,7 +22947,7 @@ }, "x-appwrite": { "method": "createMfaRecoveryCodes", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -21205,9 +22961,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21255,7 +23008,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -21269,9 +23022,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21338,7 +23088,7 @@ }, "x-appwrite": { "method": "updatePassword", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -21352,9 +23102,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21421,7 +23168,7 @@ }, "x-appwrite": { "method": "updatePhone", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -21435,9 +23182,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21504,7 +23248,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -21518,9 +23262,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21566,7 +23307,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -21580,9 +23321,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21649,7 +23387,7 @@ }, "x-appwrite": { "method": "listSessions", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -21663,9 +23401,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21711,7 +23446,7 @@ }, "x-appwrite": { "method": "createSession", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -21725,9 +23460,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21766,7 +23498,7 @@ }, "x-appwrite": { "method": "deleteSessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -21780,9 +23512,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21823,7 +23552,7 @@ }, "x-appwrite": { "method": "deleteSession", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -21837,9 +23566,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21897,7 +23623,7 @@ }, "x-appwrite": { "method": "updateStatus", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -21911,9 +23637,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21980,7 +23703,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -21995,9 +23718,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22056,7 +23776,7 @@ }, "x-appwrite": { "method": "createTarget", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -22071,9 +23791,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22169,7 +23886,7 @@ }, "x-appwrite": { "method": "getTarget", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -22184,9 +23901,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22242,7 +23956,7 @@ }, "x-appwrite": { "method": "updateTarget", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -22257,9 +23971,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22334,7 +24045,7 @@ }, "x-appwrite": { "method": "deleteTarget", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -22349,9 +24060,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22409,7 +24117,7 @@ }, "x-appwrite": { "method": "createToken", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -22423,9 +24131,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22494,7 +24199,7 @@ }, "x-appwrite": { "method": "updateEmailVerification", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -22508,9 +24213,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22577,7 +24279,7 @@ }, "x-appwrite": { "method": "updatePhoneVerification", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -22591,9 +24293,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22692,6 +24391,11 @@ "description": "The Users service allows you to manage your project users.", "x-globalAttributes": [] }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, { "name": "functions", "description": "The Functions Service allows you view, create and manage your Cloud Functions.", @@ -23050,6 +24754,30 @@ "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", @@ -23074,6 +24802,30 @@ "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", @@ -25663,6 +27415,192 @@ "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", @@ -25707,19 +27645,39 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "x-example": false }, "runtime": { "type": "string", - "description": "Function execution runtime.", + "description": "Function execution and build runtime.", "x-example": "python-3.8" }, - "deployment": { + "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.", @@ -25746,7 +27704,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { @@ -25811,7 +27769,11 @@ "live", "logging", "runtime", - "deployment", + "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "scopes", "vars", "events", @@ -25887,6 +27849,99 @@ "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", @@ -25926,7 +27981,7 @@ "description": "The entrypoint file to use to execute the deployment code.", "x-example": "index.js" }, - "size": { + "sourceSize": { "type": "integer", "description": "The code size in bytes.", "x-example": 128, @@ -25938,6 +27993,12 @@ "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.", @@ -25948,9 +28009,19 @@ "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 \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".", + "description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", "x-example": "ready" }, "buildLogs": { @@ -25958,7 +28029,7 @@ "description": "The build logs.", "x-example": "Compiling source files..." }, - "buildTime": { + "buildDuration": { "type": "integer", "description": "The current build time in seconds.", "x-example": 128, @@ -26023,13 +28094,16 @@ "resourceId", "resourceType", "entrypoint", - "size", + "sourceSize", "buildSize", + "totalSize", "buildId", "activate", + "screenshotLight", + "screenshotDark", "status", "buildLogs", - "buildTime", + "buildDuration", "providerRepositoryName", "providerRepositoryOwner", "providerRepositoryUrl", @@ -26143,7 +28217,7 @@ }, "duration": { "type": "number", - "description": "Function execution duration in seconds.", + "description": "Resource(function\/site) execution duration in seconds.", "x-example": 0.4, "format": "double" }, @@ -26173,70 +28247,6 @@ "duration" ] }, - "build": { - "description": "Build", - "type": "object", - "properties": { - "$id": { - "type": "string", - "description": "Build ID.", - "x-example": "5e5ea5c16897e" - }, - "deploymentId": { - "type": "string", - "description": "The deployment that created this build.", - "x-example": "5e5ea5c16897e" - }, - "status": { - "type": "string", - "description": "The build status. There are a few different types and each one means something different. \\nFailed - The deployment build has failed. More details can usually be found in buildStderr\\nReady - The deployment build was successful and the deployment is ready to be deployed\\nProcessing - The deployment is currently waiting to have a build triggered\\nBuilding - The deployment is currently being built", - "x-example": "ready" - }, - "stdout": { - "type": "string", - "description": "The stdout of the build.", - "x-example": "" - }, - "stderr": { - "type": "string", - "description": "The stderr of the build.", - "x-example": "" - }, - "startTime": { - "type": "string", - "description": "The deployment creation date in ISO 8601 format.", - "x-example": "2020-10-15T06:38:00.000+00:00" - }, - "endTime": { - "type": "string", - "description": "The time the build was finished in ISO 8601 format.", - "x-example": "2020-10-15T06:38:00.000+00:00" - }, - "duration": { - "type": "integer", - "description": "The build duration in seconds.", - "x-example": 0, - "format": "int32" - }, - "size": { - "type": "integer", - "description": "The code size in bytes.", - "x-example": 128, - "format": "int32" - } - }, - "required": [ - "$id", - "deploymentId", - "status", - "stdout", - "stderr", - "startTime", - "endTime", - "duration", - "size" - ] - }, "variable": { "description": "Variable", "type": "object", @@ -26266,6 +28276,11 @@ "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\"", @@ -26283,6 +28298,7 @@ "$updatedAt", "key", "value", + "secret", "resourceType", "resourceId" ] diff --git a/app/config/specs/swagger2-1.6.x-client.json b/app/config/specs/swagger2-1.6.x-client.json index b1b9ce8dca..8960bfaa5c 100644 --- a/app/config/specs/swagger2-1.6.x-client.json +++ b/app/config/specs/swagger2-1.6.x-client.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "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", @@ -102,9 +102,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -155,9 +152,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -248,9 +242,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -330,9 +321,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -394,9 +382,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -459,9 +444,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -512,9 +494,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -581,9 +560,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -656,9 +632,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -724,9 +697,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -805,9 +775,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -875,9 +842,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -922,14 +886,19 @@ "consumes": [ "application\/json" ], - "produces": [], + "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": { - "204": { - "description": "No content" + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } } }, "x-appwrite": { @@ -949,9 +918,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1031,9 +997,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1086,9 +1049,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1139,9 +1099,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1192,9 +1149,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1247,9 +1201,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1322,9 +1273,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1403,9 +1351,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1485,9 +1430,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1538,9 +1480,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1616,9 +1555,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1696,9 +1632,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1785,9 +1718,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1833,9 +1763,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1888,9 +1815,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1941,9 +1865,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2021,9 +1942,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2098,9 +2016,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2236,9 +2151,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2316,9 +2228,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2396,9 +2305,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2459,9 +2365,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2517,9 +2420,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2582,9 +2482,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2611,7 +2508,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2627,7 +2524,7 @@ "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2636,9 +2533,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2697,7 +2591,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2713,7 +2607,7 @@ "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2722,9 +2616,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2770,13 +2661,11 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "account" ], - "description": "", + "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" @@ -2789,7 +2678,7 @@ "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2798,9 +2687,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2862,9 +2748,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2922,7 +2805,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2951,9 +2834,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3040,9 +2920,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3181,9 +3058,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3261,9 +3135,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3334,9 +3205,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3419,9 +3287,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3472,9 +3337,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3555,9 +3417,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3684,9 +3543,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3701,7 +3557,7 @@ "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.", + "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", @@ -3721,7 +3577,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3740,7 +3597,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ], "in": "path" }, @@ -3817,9 +3675,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3884,9 +3739,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4375,9 +4227,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4462,9 +4311,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4557,9 +4403,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4652,9 +4495,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4709,7 +4549,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -4736,9 +4576,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4844,9 +4681,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4936,9 +4770,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5035,9 +4866,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5117,9 +4945,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5202,9 +5027,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5323,9 +5145,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5397,9 +5216,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5473,9 +5289,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5549,9 +5362,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5605,9 +5415,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5661,9 +5468,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5717,9 +5521,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5773,9 +5574,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5829,9 +5627,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -5885,9 +5680,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5941,9 +5733,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5981,7 +5770,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -5998,9 +5787,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6056,9 +5842,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -6070,7 +5854,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -6087,9 +5871,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6161,9 +5942,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6246,9 +6024,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6340,9 +6115,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6412,9 +6184,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6503,9 +6272,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6577,9 +6343,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6651,9 +6414,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6802,6 +6562,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -6852,9 +6613,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6926,9 +6684,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7003,9 +6758,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7097,9 +6849,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7161,9 +6910,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7238,9 +6984,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7304,9 +7047,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7389,9 +7129,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7506,9 +7243,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7578,9 +7312,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7666,9 +7397,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7739,9 +7467,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7837,9 +7562,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7900,9 +7622,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } diff --git a/app/config/specs/swagger2-1.6.x-console.json b/app/config/specs/swagger2-1.6.x-console.json index 9ce9d5f60d..8fc7e7daf3 100644 --- a/app/config/specs/swagger2-1.6.x-console.json +++ b/app/config/specs/swagger2-1.6.x-console.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "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", @@ -114,9 +114,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -166,9 +163,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -251,9 +245,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -304,9 +295,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -385,9 +373,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -448,9 +433,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -512,9 +494,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -565,9 +544,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -633,9 +609,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -707,9 +680,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -774,9 +744,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -854,9 +821,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -923,9 +887,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -970,14 +931,19 @@ "consumes": [ "application\/json" ], - "produces": [], + "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": { - "204": { - "description": "No content" + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } } }, "x-appwrite": { @@ -997,9 +963,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1078,9 +1041,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1132,9 +1092,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1184,9 +1141,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1236,9 +1190,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1290,9 +1241,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1364,9 +1312,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1444,9 +1389,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1525,9 +1467,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1577,9 +1516,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1654,9 +1590,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1733,9 +1666,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1821,9 +1751,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1868,9 +1795,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1922,9 +1846,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1975,9 +1896,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2055,9 +1973,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2132,9 +2047,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2270,9 +2182,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2350,9 +2259,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2430,9 +2336,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2492,9 +2395,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2549,9 +2449,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2613,9 +2510,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2641,7 +2535,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2657,7 +2551,7 @@ "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2666,9 +2560,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2726,7 +2617,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2742,7 +2633,7 @@ "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2751,9 +2642,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2798,13 +2686,11 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "account" ], - "description": "", + "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" @@ -2817,7 +2703,7 @@ "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2826,9 +2712,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2889,9 +2772,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2949,7 +2829,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2978,9 +2858,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3067,9 +2944,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3208,9 +3082,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3288,9 +3159,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3360,9 +3228,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3444,9 +3309,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3496,9 +3358,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3578,9 +3437,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3707,9 +3563,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3724,7 +3577,7 @@ "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.", + "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", @@ -3744,7 +3597,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3763,7 +3617,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ], "in": "path" }, @@ -3840,9 +3695,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3907,9 +3759,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4398,9 +4247,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4485,9 +4331,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4580,9 +4423,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4648,7 +4488,7 @@ "tags": [ "assistant" ], - "description": "", + "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", @@ -4673,9 +4513,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4745,9 +4582,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4797,9 +4631,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4871,9 +4702,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4932,7 +4760,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -4948,7 +4776,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -4957,9 +4785,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5031,9 +4856,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5092,9 +4914,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5172,9 +4991,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5235,9 +5051,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5317,9 +5130,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5426,9 +5236,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5495,9 +5302,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5598,9 +5402,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5669,9 +5470,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5752,9 +5550,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5829,7 +5624,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5858,9 +5655,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5968,9 +5762,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6045,7 +5836,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6074,9 +5867,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6184,9 +5974,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6261,7 +6048,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6290,9 +6079,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6400,9 +6186,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6487,7 +6270,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6516,9 +6301,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6636,9 +6418,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6725,7 +6504,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6754,9 +6535,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6831,8 +6609,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6878,9 +6654,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6967,7 +6740,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6996,9 +6771,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7073,8 +6845,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -7120,9 +6890,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7197,7 +6964,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7226,9 +6995,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7336,9 +7102,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7471,9 +7234,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7561,7 +7321,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7590,9 +7352,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7706,9 +7465,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7783,7 +7539,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7812,9 +7570,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7953,9 +7708,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8024,9 +7776,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8071,7 +7820,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -8100,9 +7851,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8208,9 +7956,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8265,7 +8010,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -8292,9 +8037,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8400,9 +8142,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8492,9 +8231,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8591,9 +8327,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8671,9 +8404,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8761,9 +8491,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8842,9 +8569,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8964,9 +8688,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9035,9 +8756,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9113,9 +8831,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9170,7 +8885,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -9186,7 +8901,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-collection-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -9195,9 +8910,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9285,9 +8997,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9334,7 +9043,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -9350,7 +9059,7 @@ "type": "", "deprecated": false, "demo": "databases\/get-database-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -9359,9 +9068,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9441,9 +9147,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9515,9 +9218,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9610,7 +9310,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9787,9 +9488,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9841,9 +9539,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9894,9 +9589,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9992,9 +9684,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10029,7 +9718,7 @@ "tags": [ "functions" ], - "description": "", + "description": "Get usage metrics and statistics for a for all functions. View statistics including total functions, 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": "UsageFunctions", @@ -10045,7 +9734,7 @@ "type": "", "deprecated": false, "demo": "functions\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-functions-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -10054,9 +9743,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10128,9 +9814,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10189,9 +9872,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10286,7 +9966,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -10431,9 +10112,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10494,9 +10172,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10576,9 +10251,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10670,9 +10342,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10739,9 +10408,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10803,9 +10469,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10843,11 +10506,13 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "functions" ], - "description": "", + "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": { "204": { "description": "No content" @@ -10860,7 +10525,7 @@ "type": "", "deprecated": false, "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -10869,9 +10534,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10928,7 +10590,7 @@ "tags": [ "functions" ], - "description": "", + "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": "Build", @@ -10944,7 +10606,7 @@ "type": "", "deprecated": false, "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-deployment-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -10953,9 +10615,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11025,9 +10684,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11099,9 +10755,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11184,9 +10837,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11305,9 +10955,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11370,9 +11017,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11416,7 +11060,7 @@ "tags": [ "functions" ], - "description": "", + "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", @@ -11432,7 +11076,7 @@ "type": "", "deprecated": false, "demo": "functions\/get-function-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-function-usage.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -11441,9 +11085,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11523,9 +11164,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11584,9 +11222,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11672,9 +11307,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11741,9 +11373,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11829,9 +11458,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11902,9 +11528,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11978,9 +11601,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12052,9 +11672,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12105,9 +11722,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12158,9 +11772,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12197,7 +11808,7 @@ }, "x-appwrite": { "method": "getCertificate", - "weight": 134, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -12211,9 +11822,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12273,9 +11881,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12312,7 +11917,7 @@ }, "x-appwrite": { "method": "getPubSub", - "weight": 130, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -12326,62 +11931,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [], - "Key": [] - } - ] - } - }, - "\/health\/queue": { - "get": { - "summary": "Get queue", - "operationId": "healthGetQueue", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "health" - ], - "description": "Check the Appwrite queue messaging servers are up and connection is successful.", - "responses": { - "200": { - "description": "Health Status", - "schema": { - "$ref": "#\/definitions\/healthStatus" - } - } - }, - "x-appwrite": { - "method": "getQueue", - "weight": 129, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "health\/get-queue.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "health.read", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12418,7 +11967,7 @@ }, "x-appwrite": { "method": "getQueueBuilds", - "weight": 136, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -12432,9 +11981,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12482,7 +12028,7 @@ }, "x-appwrite": { "method": "getQueueCertificates", - "weight": 135, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -12496,9 +12042,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12546,7 +12089,7 @@ }, "x-appwrite": { "method": "getQueueDatabases", - "weight": 137, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -12560,9 +12103,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12619,7 +12159,7 @@ }, "x-appwrite": { "method": "getQueueDeletes", - "weight": 138, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -12633,9 +12173,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12697,9 +12234,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12723,8 +12257,9 @@ "v1-audits", "v1-mails", "v1-functions", - "v1-usage", - "v1-usage-dump", + "v1-stats-resources", + "v1-stats-usage", + "v1-stats-usage-dump", "v1-webhooks", "v1-certificates", "v1-builds", @@ -12771,7 +12306,7 @@ }, "x-appwrite": { "method": "getQueueFunctions", - "weight": 142, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -12785,9 +12320,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12835,7 +12367,7 @@ }, "x-appwrite": { "method": "getQueueLogs", - "weight": 133, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -12849,9 +12381,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12899,7 +12428,7 @@ }, "x-appwrite": { "method": "getQueueMails", - "weight": 139, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -12913,9 +12442,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12963,7 +12489,7 @@ }, "x-appwrite": { "method": "getQueueMessaging", - "weight": 140, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -12977,9 +12503,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13027,7 +12550,7 @@ }, "x-appwrite": { "method": "getQueueMigrations", - "weight": 141, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -13041,9 +12564,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13067,9 +12587,70 @@ ] } }, - "\/health\/queue\/usage": { + "\/health\/queue\/stats-resources": { "get": { - "summary": "Get usage queue", + "summary": "Get stats resources queue", + "operationId": "healthGetQueueStatsResources", + "consumes": [ + "application\/json" + ], + "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", + "weight": 142, + "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": [ "application\/json" @@ -13096,7 +12677,7 @@ "type": "", "deprecated": false, "demo": "health\/get-queue-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -13105,9 +12686,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13131,10 +12709,10 @@ ] } }, - "\/health\/queue\/usage-dump": { + "\/health\/queue\/stats-usage-dump": { "get": { "summary": "Get usage dump queue", - "operationId": "healthGetQueueUsageDump", + "operationId": "healthGetQueueStatsUsageDump", "consumes": [ "application\/json" ], @@ -13154,13 +12732,13 @@ } }, "x-appwrite": { - "method": "getQueueUsageDump", + "method": "getQueueStatsUsageDump", "weight": 144, "cookies": false, "type": "", "deprecated": false, - "demo": "health\/get-queue-usage-dump.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-usage-dump.md", + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -13169,9 +12747,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13219,7 +12794,7 @@ }, "x-appwrite": { "method": "getQueueWebhooks", - "weight": 132, + "weight": 131, "cookies": false, "type": "", "deprecated": false, @@ -13233,9 +12808,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13297,9 +12869,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13350,9 +12919,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13389,7 +12955,7 @@ }, "x-appwrite": { "method": "getTime", - "weight": 131, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -13403,9 +12969,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13458,9 +13021,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13514,9 +13074,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13570,9 +13127,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13626,9 +13180,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13682,9 +13233,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13738,9 +13286,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -13794,9 +13339,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13850,9 +13392,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13890,7 +13429,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -13905,9 +13444,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13967,7 +13503,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -13982,9 +13518,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14116,7 +13649,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -14127,7 +13660,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -14142,9 +13675,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14284,7 +13814,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -14299,9 +13829,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14328,13 +13855,13 @@ "title": { "type": "string", "description": "Title for push notification.", - "default": null, + "default": "", "x-example": "<TITLE>" }, "body": { "type": "string", "description": "Body for push notification.", - "default": null, + "default": "", "x-example": "<BODY>" }, "topics": { @@ -14366,7 +13893,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "default": {}, "x-example": "{}" }, @@ -14390,7 +13917,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "default": "", "x-example": "<SOUND>" }, @@ -14407,10 +13934,10 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "default": "", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "default": -1, + "x-example": null }, "draft": { "type": "boolean", @@ -14423,12 +13950,34 @@ "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", - "title", - "body" + "messageId" ] } } @@ -14448,7 +13997,7 @@ "tags": [ "messaging" ], - "description": "Update a push notification by its unique ID.\n", + "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", @@ -14459,7 +14008,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -14474,9 +14023,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14600,6 +14146,30 @@ "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": [] } } } @@ -14631,7 +14201,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -14646,9 +14216,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14740,7 +14307,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -14751,12 +14318,12 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.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}", @@ -14766,9 +14333,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14869,7 +14433,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -14884,9 +14448,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14914,9 +14475,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -14928,7 +14487,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -14943,9 +14502,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14992,7 +14548,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -15007,9 +14563,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15068,7 +14621,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -15083,9 +14636,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15144,7 +14694,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -15159,9 +14709,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15221,7 +14768,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -15236,9 +14783,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15338,7 +14882,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -15353,9 +14897,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15453,7 +14994,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -15468,9 +15009,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15546,7 +15084,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -15561,9 +15099,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15637,7 +15172,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -15652,9 +15187,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15766,7 +15298,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -15781,9 +15313,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15893,7 +15422,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -15908,9 +15437,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15998,7 +15524,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -16013,9 +15539,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16101,7 +15624,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16116,9 +15639,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16218,7 +15738,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -16233,9 +15753,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16333,7 +15850,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16348,9 +15865,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16494,7 +16008,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -16509,9 +16023,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16652,7 +16163,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16667,9 +16178,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16757,7 +16265,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -16772,9 +16280,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16860,7 +16365,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16875,9 +16380,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16965,7 +16467,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -16980,9 +16482,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17068,7 +16567,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17083,9 +16582,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17173,7 +16669,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -17188,9 +16684,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17276,7 +16769,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -17291,9 +16784,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17381,7 +16871,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -17396,9 +16886,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17484,7 +16971,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -17499,9 +16986,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17529,9 +17013,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -17543,7 +17025,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -17558,9 +17040,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17607,7 +17086,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -17622,9 +17101,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17683,7 +17159,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -17698,9 +17174,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17759,7 +17232,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -17774,9 +17247,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17834,7 +17304,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -17849,9 +17319,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17926,7 +17393,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -17941,9 +17408,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17988,7 +17452,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -18003,9 +17467,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18057,9 +17518,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -18071,7 +17530,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -18086,9 +17545,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18135,7 +17591,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -18150,9 +17606,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18211,7 +17664,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -18226,9 +17679,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18294,7 +17744,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -18311,9 +17761,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18386,7 +17833,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -18401,9 +17848,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18439,9 +17883,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -18453,7 +17895,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -18470,9 +17912,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18517,7 +17956,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18528,7 +17967,7 @@ }, "x-appwrite": { "method": "list", - "weight": 339, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -18542,9 +17981,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18592,7 +18028,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18617,9 +18053,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18647,19 +18080,19 @@ }, "endpoint": { "type": "string", - "description": "Source's Appwrite Endpoint", + "description": "Source Appwrite endpoint", "default": null, "x-example": "https:\/\/example.com" }, "projectId": { "type": "string", - "description": "Source's Project ID", + "description": "Source Project ID", "default": null, "x-example": "<PROJECT_ID>" }, "apiKey": { "type": "string", - "description": "Source's API Key", + "description": "Source API Key", "default": null, "x-example": "<API_KEY>" } @@ -18688,7 +18121,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18699,7 +18132,7 @@ }, "x-appwrite": { "method": "getAppwriteReport", - "weight": 341, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -18713,9 +18146,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18767,7 +18197,7 @@ }, "\/migrations\/firebase": { "post": { - "summary": "Migrate Firebase data (Service Account)", + "summary": "Migrate Firebase data", "operationId": "migrationsCreateFirebaseMigration", "consumes": [ "application\/json" @@ -18778,7 +18208,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18789,7 +18219,7 @@ }, "x-appwrite": { "method": "createFirebaseMigration", - "weight": 336, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -18803,9 +18233,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18847,192 +18274,6 @@ ] } }, - "\/migrations\/firebase\/deauthorize": { - "get": { - "summary": "Revoke Appwrite's authorization to access Firebase projects", - "operationId": "migrationsDeleteFirebaseAuth", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "File", - "schema": { - "type": "file" - } - } - }, - "x-appwrite": { - "method": "deleteFirebaseAuth", - "weight": 347, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/delete-firebase-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, - "\/migrations\/firebase\/oauth": { - "post": { - "summary": "Migrate Firebase data (OAuth)", - "operationId": "migrationsCreateFirebaseOAuthMigration", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "202": { - "description": "Migration", - "schema": { - "$ref": "#\/definitions\/migration" - } - } - }, - "x-appwrite": { - "method": "createFirebaseOAuthMigration", - "weight": 335, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/create-firebase-o-auth-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, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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" - } - }, - "projectId": { - "type": "string", - "description": "Project ID of the Firebase Project", - "default": null, - "x-example": "<PROJECT_ID>" - } - }, - "required": [ - "resources", - "projectId" - ] - } - } - ] - } - }, - "\/migrations\/firebase\/projects": { - "get": { - "summary": "List Firebase projects", - "operationId": "migrationsListFirebaseProjects", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migrations Firebase Projects List", - "schema": { - "$ref": "#\/definitions\/firebaseProjectList" - } - } - }, - "x-appwrite": { - "method": "listFirebaseProjects", - "weight": 346, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/list-firebase-projects.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.read", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, "\/migrations\/firebase\/report": { "get": { "summary": "Generate a report on Firebase data", @@ -19046,7 +18287,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19057,7 +18298,7 @@ }, "x-appwrite": { "method": "getFirebaseReport", - "weight": 342, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -19071,9 +18312,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19106,79 +18344,6 @@ ] } }, - "\/migrations\/firebase\/report\/oauth": { - "get": { - "summary": "Generate a report on Firebase data using OAuth", - "operationId": "migrationsGetFirebaseReportOAuth", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migration Report", - "schema": { - "$ref": "#\/definitions\/migrationReport" - } - } - }, - "x-appwrite": { - "method": "getFirebaseReportOAuth", - "weight": 343, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/get-firebase-report-o-auth.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, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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": "projectId", - "description": "Project ID", - "required": true, - "type": "string", - "x-example": "<PROJECT_ID>", - "in": "query" - } - ] - } - }, "\/migrations\/nhost": { "post": { "summary": "Migrate NHost data", @@ -19192,7 +18357,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19203,7 +18368,7 @@ }, "x-appwrite": { "method": "createNHostMigration", - "weight": 338, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -19217,9 +18382,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19315,7 +18477,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19326,7 +18488,7 @@ }, "x-appwrite": { "method": "getNHostReport", - "weight": 349, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -19340,9 +18502,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19437,7 +18596,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19448,7 +18607,7 @@ }, "x-appwrite": { "method": "createSupabaseMigration", - "weight": 337, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -19462,9 +18621,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19553,7 +18709,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19564,7 +18720,7 @@ }, "x-appwrite": { "method": "getSupabaseReport", - "weight": 348, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -19578,9 +18734,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19668,7 +18821,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19679,7 +18832,7 @@ }, "x-appwrite": { "method": "get", - "weight": 340, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -19693,9 +18846,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19728,7 +18878,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Retry a failed migration. This endpoint allows you to retry a migration that has previously failed.", "responses": { "202": { "description": "Migration", @@ -19739,7 +18889,7 @@ }, "x-appwrite": { "method": "retry", - "weight": 350, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -19753,9 +18903,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19786,7 +18933,7 @@ "tags": [ "migrations" ], - "description": "", + "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" @@ -19794,7 +18941,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 351, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -19808,9 +18955,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19845,7 +18989,7 @@ "tags": [ "project" ], - "description": "", + "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", @@ -19861,7 +19005,7 @@ "type": "", "deprecated": false, "demo": "project\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -19870,9 +19014,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19956,9 +19097,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20006,9 +19144,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20085,9 +19220,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20145,9 +19277,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20224,9 +19353,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20261,7 +19387,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all projects. You can use the query params to filter your results. ", "responses": { "200": { "description": "Projects List", @@ -20277,7 +19403,7 @@ "type": "", "deprecated": false, "demo": "projects\/list.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20286,9 +19412,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20334,7 +19457,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new project. You can create a maximum of 100 projects per account. ", "responses": { "201": { "description": "Project", @@ -20350,7 +19473,7 @@ "type": "", "deprecated": false, "demo": "projects\/create.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20359,9 +19482,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20486,7 +19606,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20502,7 +19622,7 @@ "type": "", "deprecated": false, "demo": "projects\/get.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20511,9 +19631,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20546,7 +19663,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a project by its unique ID.", "responses": { "200": { "description": "Project", @@ -20562,7 +19679,7 @@ "type": "", "deprecated": false, "demo": "projects\/update.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20571,9 +19688,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20676,7 +19790,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a project by its unique ID.", "responses": { "204": { "description": "No content" @@ -20689,7 +19803,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20698,9 +19812,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20735,7 +19846,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20751,7 +19862,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-api-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20760,9 +19871,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20829,7 +19937,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20845,7 +19953,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-api-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20854,9 +19962,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20909,7 +20014,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update how long sessions created within a project should stay active for.", "responses": { "200": { "description": "Project", @@ -20925,7 +20030,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-duration.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20934,9 +20039,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20989,7 +20091,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the maximum number of users allowed in this project. Set to 0 for unlimited users. ", "responses": { "200": { "description": "Project", @@ -21005,7 +20107,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21014,9 +20116,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21069,7 +20168,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21085,7 +20184,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-sessions-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21094,9 +20193,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21149,7 +20245,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21165,7 +20261,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-memberships-privacy.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21174,9 +20270,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21243,7 +20336,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the list of mock phone numbers for testing. Use these numbers to bypass SMS verification in development. ", "responses": { "200": { "description": "Project", @@ -21259,7 +20352,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-mock-numbers.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21268,9 +20361,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21326,7 +20416,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21342,7 +20432,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-password-dictionary.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21351,9 +20441,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21406,7 +20493,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21422,7 +20509,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-password-history.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21431,9 +20518,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21486,7 +20570,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21502,7 +20586,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-personal-data-check.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21511,9 +20595,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21566,7 +20647,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Enable or disable session email alerts. When enabled, users will receive email notifications when new sessions are created.", "responses": { "200": { "description": "Project", @@ -21582,7 +20663,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-session-alerts.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21591,9 +20672,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21646,7 +20724,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21662,7 +20740,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-auth-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21671,9 +20749,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21745,7 +20820,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new JWT token. This token can be used to authenticate users with custom scopes and expiration time. ", "responses": { "201": { "description": "JWT", @@ -21761,7 +20836,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-j-w-t.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21770,9 +20845,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21834,7 +20906,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all API keys from the current project. ", "responses": { "200": { "description": "API Keys List", @@ -21850,7 +20922,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-keys.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21859,9 +20931,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21894,7 +20963,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21910,7 +20979,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21919,9 +20988,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21990,7 +21056,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22006,7 +21072,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22015,9 +21081,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22058,7 +21121,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22074,7 +21137,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22083,9 +21146,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22158,7 +21218,7 @@ "tags": [ "projects" ], - "description": "", + "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" @@ -22171,7 +21231,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22180,9 +21240,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22225,7 +21282,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22241,7 +21298,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-o-auth2.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22250,9 +21307,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22366,7 +21420,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22382,7 +21436,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-platforms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22391,9 +21445,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22426,7 +21477,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22442,7 +21493,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22451,9 +21502,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22550,7 +21598,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22566,7 +21614,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22575,9 +21623,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22618,7 +21663,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22634,7 +21679,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22643,9 +21688,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22720,7 +21762,7 @@ "tags": [ "projects" ], - "description": "", + "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" @@ -22733,7 +21775,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22742,9 +21784,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22787,7 +21826,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of a specific service. Use this endpoint to enable or disable a service in your project. ", "responses": { "200": { "description": "Project", @@ -22803,7 +21842,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-service-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22812,9 +21851,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22889,7 +21925,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of all services. Use this endpoint to enable or disable all optional services at once. ", "responses": { "200": { "description": "Project", @@ -22905,7 +21941,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-service-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22914,9 +21950,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22969,7 +22002,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22985,7 +22018,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-smtp.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22994,9 +22027,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23097,11 +22127,13 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "projects" ], - "description": "", + "description": "Send a test email to verify SMTP configuration. ", "responses": { "204": { "description": "No content" @@ -23114,7 +22146,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-smtp-test.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23123,9 +22155,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23238,7 +22267,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the team ID of a project allowing for it to be transferred to another team.", "responses": { "200": { "description": "Project", @@ -23254,7 +22283,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-team.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23263,9 +22292,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23318,7 +22344,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -23334,7 +22360,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23343,9 +22369,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23540,12 +22563,12 @@ "tags": [ "projects" ], - "description": "", + "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": "Project", + "description": "EmailTemplate", "schema": { - "$ref": "#\/definitions\/project" + "$ref": "#\/definitions\/emailTemplate" } } }, @@ -23556,7 +22579,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23565,9 +22588,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23805,7 +22825,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -23821,7 +22841,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23830,9 +22850,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24029,7 +23046,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a custom SMS template for the specified locale and type returning it's contents.", "responses": { "200": { "description": "SmsTemplate", @@ -24045,7 +23062,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24054,9 +23071,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24248,7 +23262,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24264,7 +23278,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24273,9 +23287,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24485,7 +23496,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24501,7 +23512,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24510,9 +23521,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24706,7 +23714,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24722,7 +23730,7 @@ "type": "", "deprecated": false, "demo": "projects\/list-webhooks.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24731,9 +23739,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24766,7 +23771,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24782,7 +23787,7 @@ "type": "", "deprecated": false, "demo": "projects\/create-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24791,9 +23796,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24888,7 +23890,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a webhook by its unique ID. This endpoint returns details about a specific webhook configured for a project. ", "responses": { "200": { "description": "Webhook", @@ -24904,7 +23906,7 @@ "type": "", "deprecated": false, "demo": "projects\/get-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24913,9 +23915,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24956,7 +23955,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24972,7 +23971,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24981,9 +23980,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25082,7 +24078,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a webhook by its unique ID. Once deleted, the webhook will no longer receive project events. ", "responses": { "204": { "description": "No content" @@ -25095,7 +24091,7 @@ "type": "", "deprecated": false, "demo": "projects\/delete-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -25104,9 +24100,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25149,7 +24142,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -25165,7 +24158,7 @@ "type": "", "deprecated": false, "demo": "projects\/update-webhook-signature.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -25174,9 +24167,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25244,9 +24234,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25317,9 +24304,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25408,9 +24392,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25463,9 +24444,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25500,7 +24478,7 @@ "tags": [ "proxy" ], - "description": "", + "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", @@ -25516,7 +24494,7 @@ "type": "", "deprecated": false, "demo": "proxy\/update-rule-verification.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -25525,9 +24503,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25587,9 +24562,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25661,9 +24633,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25802,9 +24771,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25863,9 +24829,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25998,9 +24961,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26063,9 +25023,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26148,9 +25105,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26242,9 +25196,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26314,9 +25265,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26405,9 +25353,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26479,9 +25424,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26553,9 +25495,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26704,6 +25643,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -26754,9 +25694,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26801,7 +25738,7 @@ "tags": [ "storage" ], - "description": "", + "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", @@ -26817,7 +25754,7 @@ "type": "", "deprecated": false, "demo": "storage\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -26826,9 +25763,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26875,7 +25809,7 @@ "tags": [ "storage" ], - "description": "", + "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", @@ -26891,7 +25825,7 @@ "type": "", "deprecated": false, "demo": "storage\/get-bucket-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -26900,9 +25834,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26984,9 +25915,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27061,9 +25989,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27155,9 +26080,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27219,9 +26141,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27296,9 +26215,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27360,9 +26276,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27436,9 +26349,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27521,9 +26431,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27638,9 +26545,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27710,9 +26614,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27798,9 +26699,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27871,9 +26769,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27968,9 +26863,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28030,9 +26922,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28111,9 +27000,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28185,9 +27071,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28282,9 +27165,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28375,9 +27255,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28468,9 +27345,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28539,9 +27413,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28602,9 +27473,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28695,9 +27563,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28788,9 +27653,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28916,9 +27778,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29030,9 +27889,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29119,7 +27975,7 @@ "tags": [ "users" ], - "description": "", + "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", @@ -29135,7 +27991,7 @@ "type": "", "deprecated": false, "demo": "users\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -29144,9 +28000,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29218,9 +28071,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29274,9 +28124,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29337,9 +28184,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29418,9 +28262,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29502,9 +28343,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29586,9 +28424,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29661,9 +28496,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29724,9 +28556,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29774,19 +28603,14 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "schema": { - "$ref": "#\/definitions\/user" - } + "204": { + "description": "No content" } }, "x-appwrite": { @@ -29805,9 +28629,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29881,9 +28702,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29944,9 +28762,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30005,9 +28820,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30066,9 +28878,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30129,9 +28938,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30210,9 +29016,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30291,9 +29094,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30372,9 +29172,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30433,9 +29230,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30514,9 +29308,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30575,9 +29366,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30631,9 +29419,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30689,9 +29474,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30760,9 +29542,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30842,9 +29621,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30916,9 +29692,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31031,9 +29804,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31101,9 +29871,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31166,9 +29933,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], @@ -31195,9 +29960,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31266,9 +30028,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31350,9 +30109,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31431,9 +30187,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31487,7 +30240,7 @@ "tags": [ "vcs" ], - "description": "", + "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": "Provider Repositories List", @@ -31503,7 +30256,7 @@ "type": "", "deprecated": false, "demo": "vcs\/list-repositories.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31512,9 +30265,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31556,7 +30306,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31572,7 +30322,7 @@ "type": "", "deprecated": false, "demo": "vcs\/create-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31581,9 +30331,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31643,7 +30390,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31659,7 +30406,7 @@ "type": "", "deprecated": false, "demo": "vcs\/get-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31668,9 +30415,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31713,7 +30457,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31729,7 +30473,7 @@ "type": "", "deprecated": false, "demo": "vcs\/list-repository-branches.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31738,9 +30482,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31783,7 +30524,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31799,7 +30540,7 @@ "type": "", "deprecated": false, "demo": "vcs\/get-repository-contents.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31808,9 +30549,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31862,7 +30600,7 @@ "tags": [ "vcs" ], - "description": "", + "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": "Detection", @@ -31878,7 +30616,7 @@ "type": "", "deprecated": false, "demo": "vcs\/create-repository-detection.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31887,9 +30625,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31941,11 +30676,13 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "vcs" ], - "description": "", + "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" @@ -31958,7 +30695,7 @@ "type": "", "deprecated": false, "demo": "vcs\/update-external-deployments.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31967,9 +30704,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -32030,7 +30764,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -32055,9 +30789,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -32105,7 +30836,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -32130,9 +30861,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -32163,7 +30891,7 @@ "tags": [ "vcs" ], - "description": "", + "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" @@ -32185,9 +30913,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -33250,31 +31975,6 @@ "migrations" ] }, - "firebaseProjectList": { - "description": "Migrations Firebase 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\/firebaseProject" - }, - "x-example": "" - } - }, - "required": [ - "total", - "projects" - ] - }, "specificationList": { "description": "Specifications List", "type": "object", @@ -35618,7 +34318,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { @@ -37494,7 +36194,8 @@ "resourceId": { "type": "string", "description": "Resource ID.", - "x-example": "5e5ea5c16897e" + "x-example": "5e5ea5c16897e", + "x-nullable": true }, "name": { "type": "string", @@ -37506,10 +36207,16 @@ "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": [ - "resourceId", "name", "value" ] @@ -37547,6 +36254,18 @@ "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.", @@ -37582,6 +36301,24 @@ "$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": [ @@ -37590,10 +36327,14 @@ "collectionsTotal", "documentsTotal", "storageTotal", + "databasesReadsTotal", + "databasesWritesTotal", "databases", "collections", "documents", - "storage" + "storage", + "databasesReads", + "databasesWrites" ] }, "usageDatabase": { @@ -37623,6 +36364,18 @@ "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.", @@ -37649,6 +36402,24 @@ "$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": [ @@ -37656,9 +36427,13 @@ "collectionsTotal", "documentsTotal", "storageTotal", + "databaseReadsTotal", + "databaseWritesTotal", "collections", "documents", - "storage" + "storage", + "databaseReads", + "databaseWrites" ] }, "usageCollection": { @@ -37843,6 +36618,21 @@ "$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": [ @@ -37850,7 +36640,9 @@ "filesTotal", "filesStorageTotal", "files", - "storage" + "storage", + "imageTransformations", + "imageTransformationsTotal" ] }, "usageFunctions": { @@ -38280,6 +37072,18 @@ "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.", @@ -38369,6 +37173,60 @@ "$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": [ @@ -38384,6 +37242,8 @@ "bucketsTotal", "executionsMbSecondsTotal", "buildsMbSecondsTotal", + "databasesReadsTotal", + "databasesWritesTotal", "requests", "network", "users", @@ -38393,7 +37253,14 @@ "databasesStorageBreakdown", "executionsMbSecondsBreakdown", "buildsMbSecondsBreakdown", - "functionsStorageBreakdown" + "functionsStorageBreakdown", + "authPhoneTotal", + "authPhoneEstimate", + "authPhoneCountryBreakdown", + "databasesReads", + "databasesWrites", + "imageTransformations", + "imageTransformationsTotal" ] }, "headers": { @@ -39274,26 +38141,6 @@ "size", "version" ] - }, - "firebaseProject": { - "description": "MigrationFirebaseProject", - "type": "object", - "properties": { - "projectId": { - "type": "string", - "description": "Project ID.", - "x-example": "my-project" - }, - "displayName": { - "type": "string", - "description": "Project display name.", - "x-example": "My Project" - } - }, - "required": [ - "projectId", - "displayName" - ] } }, "externalDocs": { diff --git a/app/config/specs/swagger2-1.6.x-server.json b/app/config/specs/swagger2-1.6.x-server.json index 2c8e80c65e..83757c94f4 100644 --- a/app/config/specs/swagger2-1.6.x-server.json +++ b/app/config/specs/swagger2-1.6.x-server.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.6.0", + "version": "1.6.1", "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", @@ -117,9 +117,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -171,9 +168,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -264,9 +258,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -347,9 +338,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -412,9 +400,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -478,9 +463,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -531,9 +513,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -601,9 +580,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -677,9 +653,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -746,9 +719,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -828,9 +798,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -899,9 +866,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -946,14 +910,19 @@ "consumes": [ "application\/json" ], - "produces": [], + "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": { - "204": { - "description": "No content" + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } } }, "x-appwrite": { @@ -973,9 +942,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1056,9 +1022,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1112,9 +1075,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1166,9 +1126,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1220,9 +1177,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1276,9 +1230,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1352,9 +1303,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1434,9 +1382,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1517,9 +1462,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1571,9 +1513,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1650,9 +1589,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1731,9 +1667,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1821,9 +1754,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1870,9 +1800,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1926,9 +1853,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1979,9 +1903,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2059,9 +1980,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2139,9 +2057,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2219,9 +2134,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2299,9 +2211,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2363,9 +2272,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2422,9 +2328,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2488,9 +2391,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2544,9 +2444,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2604,7 +2501,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2633,9 +2530,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2722,9 +2616,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2863,9 +2754,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2943,9 +2831,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3017,9 +2902,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3103,9 +2985,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3157,9 +3036,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3241,9 +3117,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3372,9 +3245,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3391,7 +3261,7 @@ "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.", + "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", @@ -3411,7 +3281,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3430,7 +3301,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ], "in": "path" }, @@ -3507,9 +3379,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3576,9 +3445,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4069,9 +3935,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4158,9 +4021,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4255,9 +4115,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4350,9 +4207,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4425,9 +4279,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4512,9 +4363,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4574,9 +4422,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4655,9 +4500,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4719,9 +4561,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4802,9 +4641,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4912,9 +4748,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4982,9 +4815,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5086,9 +4916,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5158,9 +4985,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5242,9 +5066,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5320,7 +5141,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5349,9 +5172,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5460,9 +5280,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5538,7 +5355,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5567,9 +5386,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5678,9 +5494,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5756,7 +5569,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5785,9 +5600,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5896,9 +5708,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5984,7 +5793,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6013,9 +5824,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6134,9 +5942,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6224,7 +6029,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6253,9 +6060,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6331,8 +6135,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6378,9 +6180,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6468,7 +6267,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6497,9 +6298,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6575,8 +6373,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6622,9 +6418,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6700,7 +6493,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6729,9 +6524,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6840,9 +6632,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6976,9 +6765,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7067,7 +6853,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7096,9 +6884,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7213,9 +6998,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7291,7 +7073,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7320,9 +7104,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7462,9 +7243,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7534,9 +7312,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7582,7 +7357,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7611,9 +7388,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7720,9 +7494,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7779,7 +7550,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -7806,9 +7577,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7916,9 +7684,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8010,9 +7775,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8111,9 +7873,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8193,9 +7952,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8275,9 +8031,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8398,9 +8151,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8470,9 +8220,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8549,9 +8296,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8624,9 +8368,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8720,7 +8461,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -8897,9 +8639,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8952,9 +8691,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9006,9 +8742,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9068,9 +8801,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9166,7 +8896,8 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24" ], "x-enum-name": null, "x-enum-keys": [] @@ -9311,9 +9042,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9375,9 +9103,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9458,9 +9183,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9553,9 +9275,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9623,9 +9342,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9688,9 +9404,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9729,11 +9442,13 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "functions" ], - "description": "", + "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": { "204": { "description": "No content" @@ -9746,7 +9461,7 @@ "type": "", "deprecated": false, "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -9755,9 +9470,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9815,7 +9527,7 @@ "tags": [ "functions" ], - "description": "", + "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": "Build", @@ -9831,7 +9543,7 @@ "type": "", "deprecated": false, "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-deployment-build.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -9840,9 +9552,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9913,9 +9622,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9988,9 +9694,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10075,9 +9778,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10198,9 +9898,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10265,9 +9962,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10337,9 +10031,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10399,9 +10090,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10488,9 +10176,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10558,9 +10243,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10647,9 +10329,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10721,9 +10400,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10799,9 +10475,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10875,9 +10548,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10929,9 +10599,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10983,9 +10650,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11023,7 +10687,7 @@ }, "x-appwrite": { "method": "getCertificate", - "weight": 134, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -11037,9 +10701,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11100,9 +10761,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11140,7 +10798,7 @@ }, "x-appwrite": { "method": "getPubSub", - "weight": 130, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -11154,63 +10812,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [], - "Key": [] - } - }, - "security": [ - { - "Project": [], - "Key": [] - } - ] - } - }, - "\/health\/queue": { - "get": { - "summary": "Get queue", - "operationId": "healthGetQueue", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "health" - ], - "description": "Check the Appwrite queue messaging servers are up and connection is successful.", - "responses": { - "200": { - "description": "Health Status", - "schema": { - "$ref": "#\/definitions\/healthStatus" - } - } - }, - "x-appwrite": { - "method": "getQueue", - "weight": 129, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "health\/get-queue.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "health.read", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11248,7 +10849,7 @@ }, "x-appwrite": { "method": "getQueueBuilds", - "weight": 136, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -11262,9 +10863,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11313,7 +10911,7 @@ }, "x-appwrite": { "method": "getQueueCertificates", - "weight": 135, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -11327,9 +10925,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11378,7 +10973,7 @@ }, "x-appwrite": { "method": "getQueueDatabases", - "weight": 137, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -11392,9 +10987,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11452,7 +11044,7 @@ }, "x-appwrite": { "method": "getQueueDeletes", - "weight": 138, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -11466,9 +11058,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11531,9 +11120,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11558,8 +11144,9 @@ "v1-audits", "v1-mails", "v1-functions", - "v1-usage", - "v1-usage-dump", + "v1-stats-resources", + "v1-stats-usage", + "v1-stats-usage-dump", "v1-webhooks", "v1-certificates", "v1-builds", @@ -11606,7 +11193,7 @@ }, "x-appwrite": { "method": "getQueueFunctions", - "weight": 142, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -11620,9 +11207,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11671,7 +11255,7 @@ }, "x-appwrite": { "method": "getQueueLogs", - "weight": 133, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -11685,9 +11269,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11736,7 +11317,7 @@ }, "x-appwrite": { "method": "getQueueMails", - "weight": 139, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -11750,9 +11331,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11801,7 +11379,7 @@ }, "x-appwrite": { "method": "getQueueMessaging", - "weight": 140, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -11815,9 +11393,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11866,7 +11441,7 @@ }, "x-appwrite": { "method": "getQueueMigrations", - "weight": 141, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -11880,9 +11455,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11907,9 +11479,71 @@ ] } }, - "\/health\/queue\/usage": { + "\/health\/queue\/stats-resources": { "get": { - "summary": "Get usage queue", + "summary": "Get stats resources queue", + "operationId": "healthGetQueueStatsResources", + "consumes": [ + "application\/json" + ], + "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", + "weight": 142, + "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": [ "application\/json" @@ -11936,7 +11570,7 @@ "type": "", "deprecated": false, "demo": "health\/get-queue-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11945,9 +11579,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11972,10 +11603,10 @@ ] } }, - "\/health\/queue\/usage-dump": { + "\/health\/queue\/stats-usage-dump": { "get": { "summary": "Get usage dump queue", - "operationId": "healthGetQueueUsageDump", + "operationId": "healthGetQueueStatsUsageDump", "consumes": [ "application\/json" ], @@ -11995,13 +11626,13 @@ } }, "x-appwrite": { - "method": "getQueueUsageDump", + "method": "getQueueStatsUsageDump", "weight": 144, "cookies": false, "type": "", "deprecated": false, - "demo": "health\/get-queue-usage-dump.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-usage-dump.md", + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -12010,9 +11641,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12061,7 +11689,7 @@ }, "x-appwrite": { "method": "getQueueWebhooks", - "weight": 132, + "weight": 131, "cookies": false, "type": "", "deprecated": false, @@ -12075,9 +11703,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12140,9 +11765,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12194,9 +11816,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12234,7 +11853,7 @@ }, "x-appwrite": { "method": "getTime", - "weight": 131, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -12248,9 +11867,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12304,9 +11920,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12362,9 +11975,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12420,9 +12030,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12478,9 +12085,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12536,9 +12140,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12594,9 +12195,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [], "Session": [] @@ -12652,9 +12250,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12710,9 +12305,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12752,7 +12344,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -12767,9 +12359,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12830,7 +12419,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -12845,9 +12434,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12980,7 +12566,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -12991,7 +12577,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -13006,9 +12592,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13149,7 +12732,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -13164,9 +12747,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13194,13 +12774,13 @@ "title": { "type": "string", "description": "Title for push notification.", - "default": null, + "default": "", "x-example": "<TITLE>" }, "body": { "type": "string", "description": "Body for push notification.", - "default": null, + "default": "", "x-example": "<BODY>" }, "topics": { @@ -13232,7 +12812,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "default": {}, "x-example": "{}" }, @@ -13256,7 +12836,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "default": "", "x-example": "<SOUND>" }, @@ -13273,10 +12853,10 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "default": "", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "default": -1, + "x-example": null }, "draft": { "type": "boolean", @@ -13289,12 +12869,34 @@ "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", - "title", - "body" + "messageId" ] } } @@ -13314,7 +12916,7 @@ "tags": [ "messaging" ], - "description": "Update a push notification by its unique ID.\n", + "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", @@ -13325,7 +12927,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -13340,9 +12942,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13467,6 +13066,30 @@ "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": [] } } } @@ -13498,7 +13121,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -13513,9 +13136,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13608,7 +13228,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -13619,12 +13239,12 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 389, "cookies": false, "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.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}", @@ -13634,9 +13254,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13738,7 +13355,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -13753,9 +13370,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13784,9 +13398,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -13798,7 +13410,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -13813,9 +13425,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13863,7 +13472,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -13878,9 +13487,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13940,7 +13546,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -13955,9 +13561,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14017,7 +13620,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -14032,9 +13635,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14095,7 +13695,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -14110,9 +13710,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14213,7 +13810,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -14228,9 +13825,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14329,7 +13923,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -14344,9 +13938,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14423,7 +14014,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -14438,9 +14029,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14515,7 +14103,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -14530,9 +14118,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14645,7 +14230,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14660,9 +14245,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14773,7 +14355,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -14788,9 +14370,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14879,7 +14458,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14894,9 +14473,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14983,7 +14559,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -14998,9 +14574,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15101,7 +14674,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -15116,9 +14689,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15217,7 +14787,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -15232,9 +14802,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15379,7 +14946,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -15394,9 +14961,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15538,7 +15102,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -15553,9 +15117,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15644,7 +15205,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -15659,9 +15220,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15748,7 +15306,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -15763,9 +15321,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15854,7 +15409,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -15869,9 +15424,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15958,7 +15510,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -15973,9 +15525,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16064,7 +15613,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -16079,9 +15628,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16168,7 +15714,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16183,9 +15729,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16274,7 +15817,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -16289,9 +15832,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16378,7 +15918,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -16393,9 +15933,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16424,9 +15961,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -16438,7 +15973,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -16453,9 +15988,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16503,7 +16035,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -16518,9 +16050,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16580,7 +16109,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -16595,9 +16124,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16657,7 +16183,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -16672,9 +16198,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16733,7 +16256,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -16748,9 +16271,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16826,7 +16346,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -16841,9 +16361,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16889,7 +16406,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -16904,9 +16421,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16959,9 +16473,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -16973,7 +16485,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -16988,9 +16500,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17038,7 +16547,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -17053,9 +16562,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17115,7 +16621,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -17130,9 +16636,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17199,7 +16702,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -17216,9 +16719,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -17293,7 +16793,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -17308,9 +16808,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17347,9 +16844,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -17361,7 +16856,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -17378,9 +16873,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -17452,9 +16944,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17527,9 +17016,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17669,9 +17155,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17731,9 +17214,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17867,9 +17347,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17933,9 +17410,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18020,9 +17494,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18116,9 +17587,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18190,9 +17658,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18283,9 +17748,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18359,9 +17821,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18435,9 +17894,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18588,6 +18044,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -18638,9 +18095,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18714,9 +18168,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18793,9 +18244,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18889,9 +18337,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18955,9 +18400,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19034,9 +18476,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19102,9 +18541,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19189,9 +18625,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19308,9 +18741,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19382,9 +18812,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19472,9 +18899,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19547,9 +18971,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19646,9 +19067,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19710,9 +19128,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19793,9 +19208,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19868,9 +19280,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19966,9 +19375,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20060,9 +19466,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20154,9 +19557,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20226,9 +19626,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20290,9 +19687,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20384,9 +19778,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20478,9 +19869,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20607,9 +19995,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20722,9 +20107,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20837,9 +20219,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20894,9 +20273,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20958,9 +20334,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21040,9 +20413,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21125,9 +20495,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21210,9 +20577,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21286,9 +20650,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21350,9 +20711,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21401,19 +20759,14 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "schema": { - "$ref": "#\/definitions\/user" - } + "204": { + "description": "No content" } }, "x-appwrite": { @@ -21432,9 +20785,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21509,9 +20859,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21573,9 +20920,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21635,9 +20979,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21697,9 +21038,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21761,9 +21099,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21843,9 +21178,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21925,9 +21257,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22007,9 +21336,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22069,9 +21395,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22151,9 +21474,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22213,9 +21533,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22270,9 +21587,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22329,9 +21643,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22401,9 +21712,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22484,9 +21792,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22559,9 +21864,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22675,9 +21977,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22746,9 +22045,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22812,9 +22108,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], @@ -22841,9 +22135,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22913,9 +22204,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22998,9 +22286,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -23080,9 +22365,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -26233,7 +25515,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { diff --git a/app/config/specs/swagger2-1.7.x-client.json b/app/config/specs/swagger2-1.7.x-client.json new file mode 100644 index 0000000000..9e46409693 --- /dev/null +++ b/app/config/specs/swagger2-1.7.x-client.json @@ -0,0 +1,9771 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.7.0", + "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", + "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" + } + }, + "paths": { + "\/account": { + "get": { + "summary": "Get account", + "operationId": "accountGet", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the currently logged in user.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "get", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": "Verify authenticator", + "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", + "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", + "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", + "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": "Create 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", + "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": [ + "application\/json" + ], + "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", + "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": "Get MFA recovery codes", + "operationId": "accountGetMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "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", + "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", + "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": "Regenerate MFA recovery codes", + "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", + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": "Create 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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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, 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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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}", + "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", + "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": [ + "application\/json" + ], + "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", + "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, 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", + "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", + "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", + "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": "Create 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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + } + ] + } + }, + "\/avatars\/credit-cards\/{code}": { + "get": { + "summary": "Get credit card icon", + "operationId": "avatarsGetCreditCard", + "consumes": [ + "application\/json" + ], + "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", + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + } + ] + } + }, + "\/avatars\/favicon": { + "get": { + "summary": "Get favicon", + "operationId": "avatarsGetFavicon", + "consumes": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + } + ] + } + }, + "\/avatars\/image": { + "get": { + "summary": "Get image from URL", + "operationId": "avatarsGetImage", + "consumes": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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.\n", + "responses": { + "201": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "createDocument", + "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, + "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": null, + "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" + } + } + }, + "required": [ + "documentId", + "data" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}": { + "get": { + "summary": "Get document", + "operationId": "databasesGetDocument", + "consumes": [ + "application\/json" + ], + "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", + "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" + } + ] + }, + "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", + "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", + "weight": 114, + "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" + } + ] + } + }, + "\/functions\/{functionId}\/executions": { + "get": { + "summary": "List executions", + "operationId": "functionsListExecutions", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Executions List", + "schema": { + "$ref": "#\/definitions\/executionList" + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "weight": 383, + "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": "", + "responses": { + "201": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "createExecution", + "weight": 381, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "getExecution", + "weight": 382, + "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", + "weight": 303, + "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", + "weight": 302, + "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": [ + "application\/json" + ], + "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", + "weight": 118, + "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": [ + "application\/json" + ], + "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", + "weight": 119, + "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": [ + "application\/json" + ], + "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", + "weight": 123, + "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": [ + "application\/json" + ], + "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", + "weight": 120, + "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": [ + "application\/json" + ], + "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", + "weight": 121, + "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": [ + "application\/json" + ], + "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", + "weight": 122, + "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": [ + "application\/json" + ], + "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", + "weight": 124, + "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": [ + "application\/json" + ], + "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", + "weight": 125, + "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", + "weight": 348, + "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", + "weight": 352, + "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": [ + "application\/json" + ], + "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", + "weight": 209, + "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", + "weight": 208, + "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": [ + "application\/json" + ], + "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", + "weight": 210, + "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", + "weight": 215, + "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", + "weight": 216, + "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": [ + "application\/json" + ], + "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", + "weight": 212, + "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" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/preview": { + "get": { + "summary": "Get file preview", + "operationId": "storageGetFilePreview", + "consumes": [ + "application\/json" + ], + "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", + "weight": 211, + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "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", + "gif", + "png", + "webp", + "heic", + "avif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "default": "", + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/view": { + "get": { + "summary": "Get file for view", + "operationId": "storageGetFileView", + "consumes": [ + "application\/json" + ], + "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", + "weight": 213, + "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" + } + ] + } + }, + "\/teams": { + "get": { + "summary": "List teams", + "operationId": "teamsList", + "consumes": [ + "application\/json" + ], + "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", + "weight": 220, + "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", + "weight": 219, + "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": [ + "application\/json" + ], + "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", + "weight": 221, + "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", + "weight": 223, + "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", + "weight": 225, + "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": [ + "application\/json" + ], + "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", + "weight": 227, + "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", + "weight": 226, + "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": [ + "application\/json" + ], + "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", + "weight": 228, + "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", + "weight": 229, + "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", + "weight": 231, + "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", + "weight": 230, + "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": [ + "application\/json" + ], + "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", + "weight": 222, + "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", + "weight": 224, + "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.", + "x-globalAttributes": [] + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.", + "x-globalAttributes": [] + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents", + "x-globalAttributes": [ + "databaseId" + ] + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location.", + "x-globalAttributes": [] + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health.", + "x-globalAttributes": [] + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files.", + "x-globalAttributes": [] + }, + { + "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", + "x-globalAttributes": [] + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users.", + "x-globalAttributes": [] + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions.", + "x-globalAttributes": [] + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.", + "x-globalAttributes": [] + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.", + "x-globalAttributes": [] + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations.", + "x-globalAttributes": [] + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project.", + "x-globalAttributes": [] + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).", + "x-globalAttributes": [] + } + ], + "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" + }, + "$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", + "$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.7.x-console.json b/app/config/specs/swagger2-1.7.x-console.json new file mode 100644 index 0000000000..2c1d094b63 --- /dev/null +++ b/app/config/specs/swagger2-1.7.x-console.json @@ -0,0 +1,42246 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.7.0", + "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", + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the currently logged in user.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "get", + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": "Verify authenticator", + "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", + "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", + "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", + "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": "Create 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", + "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": [ + "application\/json" + ], + "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", + "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": "Get MFA recovery codes", + "operationId": "accountGetMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "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", + "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", + "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": "Regenerate MFA recovery codes", + "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", + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": "Create 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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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, 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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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}", + "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", + "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": [ + "application\/json" + ], + "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", + "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, 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", + "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", + "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", + "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": "Create 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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + } + ] + } + }, + "\/avatars\/credit-cards\/{code}": { + "get": { + "summary": "Get credit card icon", + "operationId": "avatarsGetCreditCard", + "consumes": [ + "application\/json" + ], + "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", + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + } + ] + } + }, + "\/avatars\/favicon": { + "get": { + "summary": "Get favicon", + "operationId": "avatarsGetFavicon", + "consumes": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + } + ] + } + }, + "\/avatars\/image": { + "get": { + "summary": "Get image from URL", + "operationId": "avatarsGetImage", + "consumes": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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": "Ask 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", + "weight": 305, + "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": [ + "application\/json" + ], + "produces": [], + "tags": [ + "console" + ], + "description": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "getResource", + "weight": 423, + "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": [ + "application\/json" + ], + "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", + "weight": 304, + "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": [ + "application\/json" + ], + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "weight": 115, + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List attributes in the collection.", + "responses": { + "200": { + "description": "Attributes List", + "schema": { + "$ref": "#\/definitions\/attributeList" + } + } + }, + "x-appwrite": { + "method": "listAttributes", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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.\n", + "responses": { + "201": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "createDocument", + "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, + "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": null, + "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" + } + } + }, + "required": [ + "documentId", + "data" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}": { + "get": { + "summary": "Get document", + "operationId": "databasesGetDocument", + "consumes": [ + "application\/json" + ], + "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", + "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" + } + ] + }, + "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", + "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", + "weight": 114, + "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": [ + "application\/json" + ], + "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", + "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}\/indexes": { + "get": { + "summary": "List indexes", + "operationId": "databasesListIndexes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List indexes in the collection.", + "responses": { + "200": { + "description": "Indexes List", + "schema": { + "$ref": "#\/definitions\/indexList" + } + } + }, + "x-appwrite": { + "method": "listIndexes", + "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", + "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" + } + } + }, + "required": [ + "key", + "type", + "attributes" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes\/{key}": { + "get": { + "summary": "Get index", + "operationId": "databasesGetIndex", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get index by ID.", + "responses": { + "200": { + "description": "Index", + "schema": { + "$ref": "#\/definitions\/index" + } + } + }, + "x-appwrite": { + "method": "getIndex", + "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", + "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": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "weight": 117, + "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": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "weight": 116, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Functions List", + "schema": { + "$ref": "#\/definitions\/functionList" + } + } + }, + "x-appwrite": { + "method": "list", + "weight": 367, + "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": "", + "responses": { + "201": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "create", + "weight": 364, + "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", + "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" + ], + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Runtimes List", + "schema": { + "$ref": "#\/definitions\/runtimeList" + } + } + }, + "x-appwrite": { + "method": "listRuntimes", + "weight": 369, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Specifications List", + "schema": { + "$ref": "#\/definitions\/specificationList" + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "weight": 370, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Function Templates List", + "schema": { + "$ref": "#\/definitions\/templateFunctionList" + } + } + }, + "x-appwrite": { + "method": "listTemplates", + "weight": 393, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Template Function", + "schema": { + "$ref": "#\/definitions\/templateFunction" + } + } + }, + "x-appwrite": { + "method": "getTemplate", + "weight": 392, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "UsageFunctions", + "schema": { + "$ref": "#\/definitions\/usageFunctions" + } + } + }, + "x-appwrite": { + "method": "listUsage", + "weight": 386, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "get", + "weight": 365, + "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": "", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "update", + "weight": 366, + "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", + "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" + ], + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "weight": 368, + "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": "", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "updateFunctionDeployment", + "weight": 373, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Deployments List", + "schema": { + "$ref": "#\/definitions\/deploymentList" + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "weight": 374, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "weight": 371, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "weight": 379, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "weight": 376, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "weight": 377, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "weight": 372, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "weight": 375, + "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": "Download deployment", + "operationId": "functionsGetDeploymentDownload", + "consumes": [ + "application\/json" + ], + "produces": [ + "*\/*" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "weight": 378, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "weight": 380, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Executions List", + "schema": { + "$ref": "#\/definitions\/executionList" + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "weight": 383, + "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": "", + "responses": { + "201": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "createExecution", + "weight": 381, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "getExecution", + "weight": 382, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteExecution", + "weight": 384, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "UsageFunction", + "schema": { + "$ref": "#\/definitions\/usageFunction" + } + } + }, + "x-appwrite": { + "method": "getUsage", + "weight": 385, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Variables List", + "schema": { + "$ref": "#\/definitions\/variableList" + } + } + }, + "x-appwrite": { + "method": "listVariables", + "weight": 389, + "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": "", + "responses": { + "201": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "createVariable", + "weight": 387, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "getVariable", + "weight": 388, + "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": "", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "weight": 390, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "weight": 391, + "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", + "weight": 303, + "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", + "weight": 302, + "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": [ + "application\/json" + ], + "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", + "weight": 126, + "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": [ + "application\/json" + ], + "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", + "weight": 148, + "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": [ + "application\/json" + ], + "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", + "weight": 129, + "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": [ + "application\/json" + ], + "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", + "weight": 134, + "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": [ + "application\/json" + ], + "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", + "weight": 128, + "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": [ + "application\/json" + ], + "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", + "weight": 130, + "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": [ + "application\/json" + ], + "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", + "weight": 136, + "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": [ + "application\/json" + ], + "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", + "weight": 135, + "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": [ + "application\/json" + ], + "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", + "weight": 137, + "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": [ + "application\/json" + ], + "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", + "weight": 138, + "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": [ + "application\/json" + ], + "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", + "weight": 149, + "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-stats-usage-dump", + "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": [ + "application\/json" + ], + "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", + "weight": 142, + "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": [ + "application\/json" + ], + "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", + "weight": 133, + "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": [ + "application\/json" + ], + "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", + "weight": 139, + "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": [ + "application\/json" + ], + "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", + "weight": 140, + "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": [ + "application\/json" + ], + "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", + "weight": 141, + "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": [ + "application\/json" + ], + "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", + "weight": 143, + "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": [ + "application\/json" + ], + "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", + "weight": 144, + "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\/stats-usage-dump": { + "get": { + "summary": "Get usage dump queue", + "operationId": "healthGetQueueStatsUsageDump", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of projects containing 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": "getQueueStatsUsageDump", + "weight": 145, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.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": [ + "application\/json" + ], + "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", + "weight": 132, + "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": [ + "application\/json" + ], + "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", + "weight": 147, + "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": [ + "application\/json" + ], + "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", + "weight": 146, + "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": [ + "application\/json" + ], + "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", + "weight": 131, + "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": [ + "application\/json" + ], + "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", + "weight": 118, + "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": [ + "application\/json" + ], + "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", + "weight": 119, + "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": [ + "application\/json" + ], + "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", + "weight": 123, + "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": [ + "application\/json" + ], + "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", + "weight": 120, + "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": [ + "application\/json" + ], + "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", + "weight": 121, + "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": [ + "application\/json" + ], + "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", + "weight": 122, + "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": [ + "application\/json" + ], + "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", + "weight": 124, + "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": [ + "application\/json" + ], + "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", + "weight": 125, + "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": [ + "application\/json" + ], + "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", + "weight": 356, + "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", + "weight": 353, + "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", + "weight": 360, + "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", + "weight": 355, + "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", + "weight": 362, + "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", + "weight": 354, + "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", + "weight": 361, + "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": [ + "application\/json" + ], + "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", + "weight": 359, + "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", + "weight": 363, + "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": [ + "application\/json" + ], + "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", + "weight": 357, + "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": [ + "application\/json" + ], + "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", + "weight": 358, + "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": [ + "application\/json" + ], + "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", + "weight": 328, + "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", + "weight": 327, + "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", + "weight": 340, + "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", + "weight": 326, + "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", + "weight": 339, + "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", + "weight": 318, + "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", + "weight": 331, + "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", + "weight": 321, + "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", + "weight": 334, + "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", + "weight": 319, + "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", + "weight": 332, + "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", + "weight": 320, + "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", + "weight": 333, + "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", + "weight": 322, + "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", + "weight": 335, + "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", + "weight": 323, + "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", + "weight": 336, + "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", + "weight": 324, + "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", + "weight": 337, + "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", + "weight": 325, + "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", + "weight": 338, + "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": [ + "application\/json" + ], + "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", + "weight": 330, + "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", + "weight": 341, + "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": [ + "application\/json" + ], + "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", + "weight": 329, + "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": [ + "application\/json" + ], + "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", + "weight": 350, + "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": [ + "application\/json" + ], + "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", + "weight": 343, + "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", + "weight": 342, + "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": [ + "application\/json" + ], + "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", + "weight": 345, + "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", + "weight": 346, + "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", + "weight": 347, + "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": [ + "application\/json" + ], + "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", + "weight": 344, + "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": [ + "application\/json" + ], + "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", + "weight": 349, + "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", + "weight": 348, + "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": [ + "application\/json" + ], + "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", + "weight": 351, + "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", + "weight": 352, + "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": [ + "application\/json" + ], + "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", + "weight": 310, + "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": "Migrate Appwrite data", + "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", + "weight": 306, + "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": "Generate a report on Appwrite data", + "operationId": "migrationsGetAppwriteReport", + "consumes": [ + "application\/json" + ], + "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", + "weight": 312, + "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\/firebase": { + "post": { + "summary": "Migrate Firebase data", + "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", + "weight": 307, + "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": "Generate a report on Firebase data", + "operationId": "migrationsGetFirebaseReport", + "consumes": [ + "application\/json" + ], + "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", + "weight": 313, + "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": "Migrate NHost data", + "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", + "weight": 309, + "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": "Generate a report on NHost Data", + "operationId": "migrationsGetNHostReport", + "consumes": [ + "application\/json" + ], + "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", + "weight": 315, + "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": "Migrate Supabase data", + "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", + "weight": 308, + "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": "Generate a report on Supabase Data", + "operationId": "migrationsGetSupabaseReport", + "consumes": [ + "application\/json" + ], + "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", + "weight": 314, + "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": [ + "application\/json" + ], + "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", + "weight": 311, + "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": "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", + "weight": 316, + "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", + "weight": 317, + "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": [ + "application\/json" + ], + "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", + "weight": 197, + "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": [ + "application\/json" + ], + "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", + "weight": 199, + "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", + "weight": 198, + "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": [ + "application\/json" + ], + "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", + "weight": 200, + "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", + "weight": 201, + "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", + "weight": 202, + "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": [ + "application\/json" + ], + "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", + "weight": 152, + "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", + "weight": 151, + "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": [ + "application\/json" + ], + "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", + "weight": 153, + "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", + "weight": 154, + "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", + "weight": 171, + "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", + "weight": 158, + "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", + "weight": 159, + "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", + "weight": 164, + "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", + "weight": 163, + "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", + "weight": 169, + "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", + "weight": 162, + "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", + "weight": 170, + "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", + "weight": 167, + "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", + "weight": 166, + "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": "Enable or disable checking user passwords for similarity with their personal data.", + "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", + "weight": 168, + "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", + "weight": 161, + "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", + "weight": 165, + "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}\/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", + "weight": 183, + "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": [ + "application\/json" + ], + "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", + "weight": 179, + "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", + "weight": 178, + "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": [ + "application\/json" + ], + "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", + "weight": 180, + "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", + "weight": 181, + "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", + "weight": 182, + "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", + "weight": 160, + "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", + "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": [ + "application\/json" + ], + "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", + "weight": 185, + "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", + "weight": 184, + "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": [ + "application\/json" + ], + "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", + "weight": 186, + "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", + "weight": 187, + "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", + "weight": 188, + "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", + "weight": 156, + "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", + "weight": 157, + "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", + "weight": 189, + "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", + "weight": 190, + "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", + "weight": 155, + "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": [ + "application\/json" + ], + "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", + "weight": 192, + "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", + "weight": 194, + "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": "Reset 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", + "weight": 196, + "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": [ + "application\/json" + ], + "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", + "weight": 191, + "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", + "weight": 193, + "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", + "weight": 195, + "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": [ + "application\/json" + ], + "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", + "weight": 173, + "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", + "weight": 172, + "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": [ + "application\/json" + ], + "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", + "weight": 174, + "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", + "weight": 175, + "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", + "weight": 177, + "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", + "weight": 176, + "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": [ + "application\/json" + ], + "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", + "weight": 289, + "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": "", + "responses": { + "201": { + "description": "Rule", + "schema": { + "$ref": "#\/definitions\/proxyRule" + } + } + }, + "x-appwrite": { + "method": "createAPIRule", + "weight": 424, + "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": "", + "responses": { + "201": { + "description": "Rule", + "schema": { + "$ref": "#\/definitions\/proxyRule" + } + } + }, + "x-appwrite": { + "method": "createFunctionRule", + "weight": 426, + "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": "", + "responses": { + "201": { + "description": "Rule", + "schema": { + "$ref": "#\/definitions\/proxyRule" + } + } + }, + "x-appwrite": { + "method": "createRedirectRule", + "weight": 427, + "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" + ] + } + }, + "required": [ + "domain", + "url", + "statusCode" + ] + } + } + ] + } + }, + "\/proxy\/rules\/site": { + "post": { + "summary": "Create site rule", + "operationId": "proxyCreateSiteRule", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "proxy" + ], + "description": "", + "responses": { + "201": { + "description": "Rule", + "schema": { + "$ref": "#\/definitions\/proxyRule" + } + } + }, + "x-appwrite": { + "method": "createSiteRule", + "weight": 425, + "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": [ + "application\/json" + ], + "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", + "weight": 290, + "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", + "weight": 291, + "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", + "weight": 292, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Sites List", + "schema": { + "$ref": "#\/definitions\/siteList" + } + } + }, + "x-appwrite": { + "method": "list", + "weight": 396, + "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": "", + "responses": { + "201": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "create", + "weight": 394, + "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", + "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": 15, + "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", + "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" + ], + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Frameworks List", + "schema": { + "$ref": "#\/definitions\/frameworkList" + } + } + }, + "x-appwrite": { + "method": "listFrameworks", + "weight": 399, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Specifications List", + "schema": { + "$ref": "#\/definitions\/specificationList" + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "weight": 422, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Site Templates List", + "schema": { + "$ref": "#\/definitions\/templateSiteList" + } + } + }, + "x-appwrite": { + "method": "listTemplates", + "weight": 418, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Template Site", + "schema": { + "$ref": "#\/definitions\/templateSite" + } + } + }, + "x-appwrite": { + "method": "getTemplate", + "weight": 419, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "UsageSites", + "schema": { + "$ref": "#\/definitions\/usageSites" + } + } + }, + "x-appwrite": { + "method": "listUsage", + "weight": 420, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "get", + "weight": 395, + "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": "", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "update", + "weight": 397, + "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", + "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": 15, + "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", + "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" + ], + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "weight": 398, + "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": "", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "updateSiteDeployment", + "weight": 405, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Deployments List", + "schema": { + "$ref": "#\/definitions\/deploymentList" + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "weight": 404, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "weight": 400, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "weight": 408, + "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 deployment", + "operationId": "sitesCreateTemplateDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "weight": 401, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "weight": 402, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "weight": 403, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "weight": 406, + "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": "Download deployment", + "operationId": "sitesGetDeploymentDownload", + "consumes": [ + "application\/json" + ], + "produces": [ + "*\/*" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "weight": 407, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "weight": 409, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Executions List", + "schema": { + "$ref": "#\/definitions\/executionList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "weight": 411, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "getLog", + "weight": 410, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteLog", + "weight": 412, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "UsageSite", + "schema": { + "$ref": "#\/definitions\/usageSite" + } + } + }, + "x-appwrite": { + "method": "getUsage", + "weight": 421, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Variables List", + "schema": { + "$ref": "#\/definitions\/variableList" + } + } + }, + "x-appwrite": { + "method": "listVariables", + "weight": 415, + "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": "", + "responses": { + "201": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "createVariable", + "weight": 413, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "getVariable", + "weight": 414, + "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": "", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "weight": 416, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "weight": 417, + "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": [ + "application\/json" + ], + "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", + "weight": 204, + "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", + "weight": 203, + "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": [ + "application\/json" + ], + "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", + "weight": 205, + "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", + "weight": 206, + "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", + "weight": 207, + "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": [ + "application\/json" + ], + "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", + "weight": 209, + "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", + "weight": 208, + "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": [ + "application\/json" + ], + "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", + "weight": 210, + "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", + "weight": 215, + "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", + "weight": 216, + "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": [ + "application\/json" + ], + "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", + "weight": 212, + "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" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/preview": { + "get": { + "summary": "Get file preview", + "operationId": "storageGetFilePreview", + "consumes": [ + "application\/json" + ], + "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", + "weight": 211, + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "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", + "gif", + "png", + "webp", + "heic", + "avif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "default": "", + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/view": { + "get": { + "summary": "Get file for view", + "operationId": "storageGetFileView", + "consumes": [ + "application\/json" + ], + "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", + "weight": 213, + "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" + } + ] + } + }, + "\/storage\/usage": { + "get": { + "summary": "Get storage usage stats", + "operationId": "storageGetUsage", + "consumes": [ + "application\/json" + ], + "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", + "weight": 217, + "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": [ + "application\/json" + ], + "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", + "weight": 218, + "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": [ + "application\/json" + ], + "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", + "weight": 220, + "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", + "weight": 219, + "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": [ + "application\/json" + ], + "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", + "weight": 221, + "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", + "weight": 223, + "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", + "weight": 225, + "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": [ + "application\/json" + ], + "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", + "weight": 232, + "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": [ + "application\/json" + ], + "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", + "weight": 227, + "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", + "weight": 226, + "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": [ + "application\/json" + ], + "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", + "weight": 228, + "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", + "weight": 229, + "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", + "weight": 231, + "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", + "weight": 230, + "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": [ + "application\/json" + ], + "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", + "weight": 222, + "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", + "weight": 224, + "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" + ] + } + } + ] + } + }, + "\/users": { + "get": { + "summary": "List users", + "operationId": "usersList", + "consumes": [ + "application\/json" + ], + "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", + "weight": 242, + "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", + "weight": 233, + "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", + "weight": 236, + "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", + "weight": 234, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get identities for all users.", + "responses": { + "200": { + "description": "Identities List", + "schema": { + "$ref": "#\/definitions\/identityList" + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "weight": 250, + "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", + "weight": 273, + "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", + "weight": 235, + "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", + "weight": 238, + "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", + "weight": 239, + "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", + "weight": 240, + "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", + "weight": 237, + "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": [ + "application\/json" + ], + "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", + "weight": 275, + "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": [ + "application\/json" + ], + "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", + "weight": 243, + "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", + "weight": 271, + "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", + "weight": 256, + "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", + "weight": 274, + "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", + "weight": 252, + "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": [ + "application\/json" + ], + "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", + "weight": 248, + "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": [ + "application\/json" + ], + "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", + "weight": 247, + "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", + "weight": 261, + "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", + "weight": 266, + "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": [ + "application\/json" + ], + "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", + "weight": 262, + "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": [ + "application\/json" + ], + "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", + "weight": 263, + "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": "Regenerate MFA recovery codes", + "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", + "weight": 265, + "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", + "weight": 264, + "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", + "weight": 254, + "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", + "weight": 255, + "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", + "weight": 257, + "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": [ + "application\/json" + ], + "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", + "weight": 244, + "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", + "weight": 259, + "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": [ + "application\/json" + ], + "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", + "weight": 246, + "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", + "weight": 267, + "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", + "weight": 270, + "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", + "weight": 269, + "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", + "weight": 251, + "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": [ + "application\/json" + ], + "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", + "weight": 249, + "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: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "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", + "weight": 241, + "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": [ + "application\/json" + ], + "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", + "weight": 245, + "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", + "weight": 260, + "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", + "weight": 272, + "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", + "weight": 268, + "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", + "weight": 258, + "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", + "weight": 253, + "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", + "weight": 279, + "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": [ + "application\/json" + ], + "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", + "weight": 280, + "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", + "weight": 281, + "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": [ + "application\/json" + ], + "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", + "weight": 282, + "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": [ + "application\/json" + ], + "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", + "weight": 283, + "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": [ + "application\/json" + ], + "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", + "weight": 278, + "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": "Authorize external deployment", + "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", + "weight": 288, + "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": [ + "application\/json" + ], + "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", + "weight": 285, + "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": [ + "application\/json" + ], + "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", + "weight": 286, + "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", + "weight": 287, + "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.", + "x-globalAttributes": [] + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.", + "x-globalAttributes": [] + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents", + "x-globalAttributes": [ + "databaseId" + ] + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location.", + "x-globalAttributes": [] + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health.", + "x-globalAttributes": [] + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files.", + "x-globalAttributes": [] + }, + { + "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", + "x-globalAttributes": [] + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users.", + "x-globalAttributes": [] + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions.", + "x-globalAttributes": [] + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.", + "x-globalAttributes": [] + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.", + "x-globalAttributes": [] + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations.", + "x-globalAttributes": [] + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project.", + "x-globalAttributes": [] + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).", + "x-globalAttributes": [] + } + ], + "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" + ] + }, + "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" + ] + }, + "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 + } + }, + "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": [] + }, + "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", + "$createdAt", + "$updatedAt" + ] + }, + "document": { + "description": "Document", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Document ID.", + "x-example": "5e5ea5c16897e" + }, + "$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", + "$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" + ] + }, + "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": {} + }, + "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", + "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" + ] + }, + "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": [] + }, + "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": [] + } + }, + "required": [ + "range", + "functionsTotal", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "functions", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds" + ] + }, + "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" + }, + "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" + }, + "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": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds" + ] + }, + "usageSites": { + "description": "UsageSites", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "sitesTotal": { + "type": "integer", + "description": "Total aggregated number of sites.", + "x-example": 0, + "format": "int32" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of sites deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of sites deployment storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of sites build.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of sites build storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of sites build compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of sites build mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "sites": { + "type": "array", + "description": "Aggregated number of sites per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": 0 + }, + "deployments": { + "type": "array", + "description": "Aggregated number of sites deployment per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of sites deployment storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "builds": { + "type": "array", + "description": "Aggregated number of sites build per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of sites build storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of sites build compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated sum of sites build mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "sitesTotal", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "sites", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds" + ] + }, + "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 site deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of site deployments storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of site builds.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of site builds storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of site builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of site builds mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "Aggregated number of site deployments per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of site deployments storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "builds": { + "type": "array", + "description": "Aggregated number of site builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of site builds storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of site builds compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated number of site builds mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds" + ] + }, + "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": { + "type": "string", + "description": "CNAME target for your Appwrite custom domains.", + "x-example": "appwrite.io" + }, + "_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", + "_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" + ] + }, + "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", + "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.7.x-server.json b/app/config/specs/swagger2-1.7.x-server.json new file mode 100644 index 0000000000..c89973e2a3 --- /dev/null +++ b/app/config/specs/swagger2-1.7.x-server.json @@ -0,0 +1,29680 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.7.0", + "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", + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the currently logged in user.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "get", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": "Verify authenticator", + "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", + "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", + "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", + "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": "Create 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", + "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": [ + "application\/json" + ], + "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", + "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": "Get MFA recovery codes", + "operationId": "accountGetMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "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", + "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", + "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": "Regenerate MFA recovery codes", + "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", + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": "Create 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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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", + "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", + "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}", + "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", + "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": [ + "application\/json" + ], + "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", + "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, 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", + "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", + "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", + "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": "Create 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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + } + ] + } + }, + "\/avatars\/credit-cards\/{code}": { + "get": { + "summary": "Get credit card icon", + "operationId": "avatarsGetCreditCard", + "consumes": [ + "application\/json" + ], + "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", + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + } + ] + } + }, + "\/avatars\/favicon": { + "get": { + "summary": "Get favicon", + "operationId": "avatarsGetFavicon", + "consumes": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + } + ] + } + }, + "\/avatars\/image": { + "get": { + "summary": "Get image from URL", + "operationId": "avatarsGetImage", + "consumes": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List attributes in the collection.", + "responses": { + "200": { + "description": "Attributes List", + "schema": { + "$ref": "#\/definitions\/attributeList" + } + } + }, + "x-appwrite": { + "method": "listAttributes", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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", + "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", + "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": [ + "application\/json" + ], + "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", + "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.\n", + "responses": { + "201": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "createDocument", + "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, + "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": null, + "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" + } + } + }, + "required": [ + "documentId", + "data" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}": { + "get": { + "summary": "Get document", + "operationId": "databasesGetDocument", + "consumes": [ + "application\/json" + ], + "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", + "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" + } + ] + }, + "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", + "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", + "weight": 114, + "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}\/indexes": { + "get": { + "summary": "List indexes", + "operationId": "databasesListIndexes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List indexes in the collection.", + "responses": { + "200": { + "description": "Indexes List", + "schema": { + "$ref": "#\/definitions\/indexList" + } + } + }, + "x-appwrite": { + "method": "listIndexes", + "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", + "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" + } + } + }, + "required": [ + "key", + "type", + "attributes" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes\/{key}": { + "get": { + "summary": "Get index", + "operationId": "databasesGetIndex", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get index by ID.", + "responses": { + "200": { + "description": "Index", + "schema": { + "$ref": "#\/definitions\/index" + } + } + }, + "x-appwrite": { + "method": "getIndex", + "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", + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Functions List", + "schema": { + "$ref": "#\/definitions\/functionList" + } + } + }, + "x-appwrite": { + "method": "list", + "weight": 367, + "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": "", + "responses": { + "201": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "create", + "weight": 364, + "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", + "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" + ], + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Runtimes List", + "schema": { + "$ref": "#\/definitions\/runtimeList" + } + } + }, + "x-appwrite": { + "method": "listRuntimes", + "weight": 369, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Specifications List", + "schema": { + "$ref": "#\/definitions\/specificationList" + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "weight": 370, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "get", + "weight": 365, + "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": "", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "update", + "weight": 366, + "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", + "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" + ], + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "weight": 368, + "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": "", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "updateFunctionDeployment", + "weight": 373, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Deployments List", + "schema": { + "$ref": "#\/definitions\/deploymentList" + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "weight": 374, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "weight": 371, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "weight": 379, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "weight": 376, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "weight": 377, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "weight": 372, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "weight": 375, + "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": "Download deployment", + "operationId": "functionsGetDeploymentDownload", + "consumes": [ + "application\/json" + ], + "produces": [ + "*\/*" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "weight": 378, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "weight": 380, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Executions List", + "schema": { + "$ref": "#\/definitions\/executionList" + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "weight": 383, + "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": "", + "responses": { + "201": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "createExecution", + "weight": 381, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "getExecution", + "weight": 382, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteExecution", + "weight": 384, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Variables List", + "schema": { + "$ref": "#\/definitions\/variableList" + } + } + }, + "x-appwrite": { + "method": "listVariables", + "weight": 389, + "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": "", + "responses": { + "201": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "createVariable", + "weight": 387, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "getVariable", + "weight": 388, + "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": "", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "weight": 390, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "weight": 391, + "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", + "weight": 303, + "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", + "weight": 302, + "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": [ + "application\/json" + ], + "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", + "weight": 126, + "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": [ + "application\/json" + ], + "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", + "weight": 148, + "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": [ + "application\/json" + ], + "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", + "weight": 129, + "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": [ + "application\/json" + ], + "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", + "weight": 134, + "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": [ + "application\/json" + ], + "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", + "weight": 128, + "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": [ + "application\/json" + ], + "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", + "weight": 130, + "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": [ + "application\/json" + ], + "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", + "weight": 136, + "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": [ + "application\/json" + ], + "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", + "weight": 135, + "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": [ + "application\/json" + ], + "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", + "weight": 137, + "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": [ + "application\/json" + ], + "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", + "weight": 138, + "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": [ + "application\/json" + ], + "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", + "weight": 149, + "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-stats-usage-dump", + "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": [ + "application\/json" + ], + "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", + "weight": 142, + "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": [ + "application\/json" + ], + "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", + "weight": 133, + "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": [ + "application\/json" + ], + "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", + "weight": 139, + "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": [ + "application\/json" + ], + "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", + "weight": 140, + "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": [ + "application\/json" + ], + "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", + "weight": 141, + "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": [ + "application\/json" + ], + "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", + "weight": 143, + "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": [ + "application\/json" + ], + "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", + "weight": 144, + "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\/stats-usage-dump": { + "get": { + "summary": "Get usage dump queue", + "operationId": "healthGetQueueStatsUsageDump", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of projects containing 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": "getQueueStatsUsageDump", + "weight": 145, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.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": [ + "application\/json" + ], + "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", + "weight": 132, + "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": [ + "application\/json" + ], + "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", + "weight": 147, + "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": [ + "application\/json" + ], + "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", + "weight": 146, + "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": [ + "application\/json" + ], + "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", + "weight": 131, + "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": [ + "application\/json" + ], + "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", + "weight": 118, + "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": [ + "application\/json" + ], + "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", + "weight": 119, + "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": [ + "application\/json" + ], + "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", + "weight": 123, + "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": [ + "application\/json" + ], + "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", + "weight": 120, + "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": [ + "application\/json" + ], + "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", + "weight": 121, + "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": [ + "application\/json" + ], + "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", + "weight": 122, + "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": [ + "application\/json" + ], + "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", + "weight": 124, + "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": [ + "application\/json" + ], + "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", + "weight": 125, + "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": [ + "application\/json" + ], + "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", + "weight": 356, + "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", + "weight": 353, + "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", + "weight": 360, + "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", + "weight": 355, + "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", + "weight": 362, + "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", + "weight": 354, + "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", + "weight": 361, + "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": [ + "application\/json" + ], + "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", + "weight": 359, + "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", + "weight": 363, + "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": [ + "application\/json" + ], + "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", + "weight": 357, + "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": [ + "application\/json" + ], + "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", + "weight": 358, + "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": [ + "application\/json" + ], + "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", + "weight": 328, + "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", + "weight": 327, + "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", + "weight": 340, + "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", + "weight": 326, + "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", + "weight": 339, + "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", + "weight": 318, + "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", + "weight": 331, + "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", + "weight": 321, + "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", + "weight": 334, + "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", + "weight": 319, + "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", + "weight": 332, + "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", + "weight": 320, + "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", + "weight": 333, + "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", + "weight": 322, + "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", + "weight": 335, + "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", + "weight": 323, + "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", + "weight": 336, + "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", + "weight": 324, + "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", + "weight": 337, + "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", + "weight": 325, + "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", + "weight": 338, + "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": [ + "application\/json" + ], + "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", + "weight": 330, + "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", + "weight": 341, + "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": [ + "application\/json" + ], + "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", + "weight": 329, + "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": [ + "application\/json" + ], + "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", + "weight": 350, + "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": [ + "application\/json" + ], + "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", + "weight": 343, + "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", + "weight": 342, + "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": [ + "application\/json" + ], + "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", + "weight": 345, + "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", + "weight": 346, + "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", + "weight": 347, + "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": [ + "application\/json" + ], + "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", + "weight": 344, + "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": [ + "application\/json" + ], + "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", + "weight": 349, + "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", + "weight": 348, + "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": [ + "application\/json" + ], + "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", + "weight": 351, + "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", + "weight": 352, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Sites List", + "schema": { + "$ref": "#\/definitions\/siteList" + } + } + }, + "x-appwrite": { + "method": "list", + "weight": 396, + "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": "", + "responses": { + "201": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "create", + "weight": 394, + "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", + "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": 15, + "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", + "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" + ], + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Frameworks List", + "schema": { + "$ref": "#\/definitions\/frameworkList" + } + } + }, + "x-appwrite": { + "method": "listFrameworks", + "weight": 399, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Specifications List", + "schema": { + "$ref": "#\/definitions\/specificationList" + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "weight": 422, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "get", + "weight": 395, + "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": "", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "update", + "weight": 397, + "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", + "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": 15, + "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", + "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" + ], + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "weight": 398, + "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": "", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "updateSiteDeployment", + "weight": 405, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Deployments List", + "schema": { + "$ref": "#\/definitions\/deploymentList" + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "weight": 404, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "weight": 400, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "weight": 408, + "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 deployment", + "operationId": "sitesCreateTemplateDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "weight": 401, + "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": "", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "weight": 402, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "weight": 403, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "weight": 406, + "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": "Download deployment", + "operationId": "sitesGetDeploymentDownload", + "consumes": [ + "application\/json" + ], + "produces": [ + "*\/*" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "weight": 407, + "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": "", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "weight": 409, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Executions List", + "schema": { + "$ref": "#\/definitions\/executionList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "weight": 411, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "getLog", + "weight": 410, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteLog", + "weight": 412, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Variables List", + "schema": { + "$ref": "#\/definitions\/variableList" + } + } + }, + "x-appwrite": { + "method": "listVariables", + "weight": 415, + "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": "", + "responses": { + "201": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "createVariable", + "weight": 413, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "getVariable", + "weight": 414, + "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": "", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "weight": 416, + "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": "", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "weight": 417, + "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": [ + "application\/json" + ], + "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", + "weight": 204, + "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", + "weight": 203, + "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": [ + "application\/json" + ], + "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", + "weight": 205, + "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", + "weight": 206, + "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", + "weight": 207, + "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": [ + "application\/json" + ], + "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", + "weight": 209, + "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", + "weight": 208, + "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": [ + "application\/json" + ], + "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", + "weight": 210, + "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", + "weight": 215, + "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", + "weight": 216, + "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": [ + "application\/json" + ], + "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", + "weight": 212, + "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" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/preview": { + "get": { + "summary": "Get file preview", + "operationId": "storageGetFilePreview", + "consumes": [ + "application\/json" + ], + "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", + "weight": 211, + "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 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "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", + "gif", + "png", + "webp", + "heic", + "avif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "default": "", + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/view": { + "get": { + "summary": "Get file for view", + "operationId": "storageGetFileView", + "consumes": [ + "application\/json" + ], + "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", + "weight": 213, + "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" + } + ] + } + }, + "\/teams": { + "get": { + "summary": "List teams", + "operationId": "teamsList", + "consumes": [ + "application\/json" + ], + "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", + "weight": 220, + "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", + "weight": 219, + "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": [ + "application\/json" + ], + "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", + "weight": 221, + "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", + "weight": 223, + "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", + "weight": 225, + "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": [ + "application\/json" + ], + "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", + "weight": 227, + "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", + "weight": 226, + "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": [ + "application\/json" + ], + "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", + "weight": 228, + "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", + "weight": 229, + "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", + "weight": 231, + "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", + "weight": 230, + "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": [ + "application\/json" + ], + "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", + "weight": 222, + "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", + "weight": 224, + "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" + ] + } + } + ] + } + }, + "\/users": { + "get": { + "summary": "List users", + "operationId": "usersList", + "consumes": [ + "application\/json" + ], + "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", + "weight": 242, + "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", + "weight": 233, + "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", + "weight": 236, + "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", + "weight": 234, + "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": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get identities for all users.", + "responses": { + "200": { + "description": "Identities List", + "schema": { + "$ref": "#\/definitions\/identityList" + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "weight": 250, + "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", + "weight": 273, + "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", + "weight": 235, + "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", + "weight": 238, + "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", + "weight": 239, + "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", + "weight": 240, + "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", + "weight": 237, + "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": [ + "application\/json" + ], + "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", + "weight": 243, + "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", + "weight": 271, + "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", + "weight": 256, + "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", + "weight": 274, + "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", + "weight": 252, + "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": [ + "application\/json" + ], + "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", + "weight": 248, + "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": [ + "application\/json" + ], + "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", + "weight": 247, + "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", + "weight": 261, + "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", + "weight": 266, + "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": [ + "application\/json" + ], + "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", + "weight": 262, + "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": [ + "application\/json" + ], + "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", + "weight": 263, + "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": "Regenerate MFA recovery codes", + "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", + "weight": 265, + "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", + "weight": 264, + "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", + "weight": 254, + "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", + "weight": 255, + "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", + "weight": 257, + "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": [ + "application\/json" + ], + "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", + "weight": 244, + "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", + "weight": 259, + "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": [ + "application\/json" + ], + "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", + "weight": 246, + "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", + "weight": 267, + "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", + "weight": 270, + "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", + "weight": 269, + "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", + "weight": 251, + "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": [ + "application\/json" + ], + "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", + "weight": 249, + "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: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "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", + "weight": 241, + "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": [ + "application\/json" + ], + "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", + "weight": 245, + "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", + "weight": 260, + "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", + "weight": 272, + "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", + "weight": 268, + "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", + "weight": 258, + "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", + "weight": 253, + "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.", + "x-globalAttributes": [] + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars.", + "x-globalAttributes": [] + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents", + "x-globalAttributes": [ + "databaseId" + ] + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location.", + "x-globalAttributes": [] + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health.", + "x-globalAttributes": [] + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server.", + "x-globalAttributes": [] + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files.", + "x-globalAttributes": [] + }, + { + "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", + "x-globalAttributes": [] + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users.", + "x-globalAttributes": [] + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions.", + "x-globalAttributes": [] + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration.", + "x-globalAttributes": [] + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL.", + "x-globalAttributes": [] + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations.", + "x-globalAttributes": [] + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project.", + "x-globalAttributes": [] + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.).", + "x-globalAttributes": [] + } + ], + "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" + ] + }, + "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 + } + }, + "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": [] + }, + "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", + "$createdAt", + "$updatedAt" + ] + }, + "document": { + "description": "Document", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Document ID.", + "x-example": "5e5ea5c16897e" + }, + "$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", + "$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" + ] + }, + "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 b1b9ce8dca..dc5600aa86 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.6.0", + "version": "1.7.0", "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", @@ -87,7 +87,7 @@ }, "x-appwrite": { "method": "get", - "weight": 9, + "weight": 10, "cookies": false, "type": "", "deprecated": false, @@ -102,9 +102,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -140,7 +137,7 @@ }, "x-appwrite": { "method": "create", - "weight": 8, + "weight": 9, "cookies": false, "type": "", "deprecated": false, @@ -155,9 +152,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -233,7 +227,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 34, + "weight": 35, "cookies": false, "type": "", "deprecated": false, @@ -248,9 +242,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -315,7 +306,7 @@ }, "x-appwrite": { "method": "listIdentities", - "weight": 57, + "weight": 58, "cookies": false, "type": "", "deprecated": false, @@ -330,9 +321,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -379,7 +367,7 @@ }, "x-appwrite": { "method": "deleteIdentity", - "weight": 58, + "weight": 59, "cookies": false, "type": "", "deprecated": false, @@ -394,9 +382,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -444,7 +429,7 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 29, + "weight": 30, "cookies": false, "type": "", "deprecated": false, @@ -459,9 +444,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -497,7 +479,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 31, + "weight": 32, "cookies": false, "type": "", "deprecated": false, @@ -512,9 +494,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -566,7 +545,7 @@ }, "x-appwrite": { "method": "updateMFA", - "weight": 44, + "weight": 45, "cookies": false, "type": "", "deprecated": false, @@ -581,9 +560,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -641,7 +617,7 @@ }, "x-appwrite": { "method": "createMfaAuthenticator", - "weight": 46, + "weight": 47, "cookies": false, "type": "", "deprecated": false, @@ -656,9 +632,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -709,7 +682,7 @@ }, "x-appwrite": { "method": "updateMfaAuthenticator", - "weight": 47, + "weight": 48, "cookies": false, "type": "", "deprecated": false, @@ -724,9 +697,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -790,7 +760,7 @@ }, "x-appwrite": { "method": "deleteMfaAuthenticator", - "weight": 51, + "weight": 52, "cookies": false, "type": "", "deprecated": false, @@ -805,9 +775,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -860,7 +827,7 @@ }, "x-appwrite": { "method": "createMfaChallenge", - "weight": 52, + "weight": 53, "cookies": false, "type": "", "deprecated": false, @@ -875,9 +842,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -922,19 +886,24 @@ "consumes": [ "application\/json" ], - "produces": [], + "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": { - "204": { - "description": "No content" + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } } }, "x-appwrite": { "method": "updateMfaChallenge", - "weight": 53, + "weight": 54, "cookies": false, "type": "", "deprecated": false, @@ -949,9 +918,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1016,7 +982,7 @@ }, "x-appwrite": { "method": "listMfaFactors", - "weight": 45, + "weight": 46, "cookies": false, "type": "", "deprecated": false, @@ -1031,9 +997,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1071,7 +1034,7 @@ }, "x-appwrite": { "method": "getMfaRecoveryCodes", - "weight": 50, + "weight": 51, "cookies": false, "type": "", "deprecated": false, @@ -1086,9 +1049,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1124,7 +1084,7 @@ }, "x-appwrite": { "method": "createMfaRecoveryCodes", - "weight": 48, + "weight": 49, "cookies": false, "type": "", "deprecated": false, @@ -1139,9 +1099,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1177,7 +1134,7 @@ }, "x-appwrite": { "method": "updateMfaRecoveryCodes", - "weight": 49, + "weight": 50, "cookies": false, "type": "", "deprecated": false, @@ -1192,9 +1149,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1232,7 +1186,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 32, + "weight": 33, "cookies": false, "type": "", "deprecated": false, @@ -1247,9 +1201,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1307,7 +1258,7 @@ }, "x-appwrite": { "method": "updatePassword", - "weight": 33, + "weight": 34, "cookies": false, "type": "", "deprecated": false, @@ -1322,9 +1273,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1388,7 +1336,7 @@ }, "x-appwrite": { "method": "updatePhone", - "weight": 35, + "weight": 36, "cookies": false, "type": "", "deprecated": false, @@ -1403,9 +1351,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1470,7 +1415,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 30, + "weight": 31, "cookies": false, "type": "", "deprecated": false, @@ -1485,9 +1430,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1523,7 +1465,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 36, + "weight": 37, "cookies": false, "type": "", "deprecated": false, @@ -1538,9 +1480,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1598,7 +1537,7 @@ }, "x-appwrite": { "method": "createRecovery", - "weight": 38, + "weight": 39, "cookies": false, "type": "", "deprecated": false, @@ -1616,9 +1555,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1681,7 +1617,7 @@ }, "x-appwrite": { "method": "updateRecovery", - "weight": 39, + "weight": 40, "cookies": false, "type": "", "deprecated": false, @@ -1696,9 +1632,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1770,7 +1703,7 @@ }, "x-appwrite": { "method": "listSessions", - "weight": 11, + "weight": 12, "cookies": false, "type": "", "deprecated": false, @@ -1785,9 +1718,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1818,7 +1748,7 @@ }, "x-appwrite": { "method": "deleteSessions", - "weight": 12, + "weight": 13, "cookies": false, "type": "", "deprecated": false, @@ -1833,9 +1763,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1873,7 +1800,7 @@ }, "x-appwrite": { "method": "createAnonymousSession", - "weight": 17, + "weight": 18, "cookies": false, "type": "", "deprecated": false, @@ -1888,9 +1815,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1926,7 +1850,7 @@ }, "x-appwrite": { "method": "createEmailPasswordSession", - "weight": 16, + "weight": 17, "cookies": false, "type": "", "deprecated": false, @@ -1941,9 +1865,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2006,7 +1927,7 @@ }, "x-appwrite": { "method": "updateMagicURLSession", - "weight": 26, + "weight": 27, "cookies": false, "type": "", "deprecated": true, @@ -2021,9 +1942,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2083,7 +2001,7 @@ }, "x-appwrite": { "method": "createOAuth2Session", - "weight": 19, + "weight": 20, "cookies": false, "type": "webAuth", "deprecated": false, @@ -2098,9 +2016,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2221,7 +2136,7 @@ }, "x-appwrite": { "method": "updatePhoneSession", - "weight": 27, + "weight": 28, "cookies": false, "type": "", "deprecated": true, @@ -2236,9 +2151,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2301,7 +2213,7 @@ }, "x-appwrite": { "method": "createSession", - "weight": 18, + "weight": 19, "cookies": false, "type": "", "deprecated": false, @@ -2316,9 +2228,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2381,7 +2290,7 @@ }, "x-appwrite": { "method": "getSession", - "weight": 13, + "weight": 14, "cookies": false, "type": "", "deprecated": false, @@ -2396,9 +2305,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2444,7 +2350,7 @@ }, "x-appwrite": { "method": "updateSession", - "weight": 15, + "weight": 16, "cookies": false, "type": "", "deprecated": false, @@ -2459,9 +2365,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2502,7 +2405,7 @@ }, "x-appwrite": { "method": "deleteSession", - "weight": 14, + "weight": 15, "cookies": false, "type": "", "deprecated": false, @@ -2517,9 +2420,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2567,7 +2467,7 @@ }, "x-appwrite": { "method": "updateStatus", - "weight": 37, + "weight": 38, "cookies": false, "type": "", "deprecated": false, @@ -2582,9 +2482,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2611,7 +2508,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2622,12 +2519,12 @@ }, "x-appwrite": { "method": "createPushTarget", - "weight": 54, + "weight": 55, "cookies": false, "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2636,9 +2533,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2697,7 +2591,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2708,12 +2602,12 @@ }, "x-appwrite": { "method": "updatePushTarget", - "weight": 55, + "weight": 56, "cookies": false, "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2722,9 +2616,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2770,13 +2661,11 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "account" ], - "description": "", + "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" @@ -2784,12 +2673,12 @@ }, "x-appwrite": { "method": "deletePushTarget", - "weight": 56, + "weight": 57, "cookies": false, "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2798,9 +2687,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2847,7 +2733,7 @@ }, "x-appwrite": { "method": "createEmailToken", - "weight": 25, + "weight": 26, "cookies": false, "type": "", "deprecated": false, @@ -2862,9 +2748,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2922,7 +2805,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2933,7 +2816,7 @@ }, "x-appwrite": { "method": "createMagicURLToken", - "weight": 24, + "weight": 25, "cookies": false, "type": "", "deprecated": false, @@ -2951,9 +2834,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3025,7 +2905,7 @@ }, "x-appwrite": { "method": "createOAuth2Token", - "weight": 23, + "weight": 24, "cookies": false, "type": "webAuth", "deprecated": false, @@ -3040,9 +2920,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3163,7 +3040,7 @@ }, "x-appwrite": { "method": "createPhoneToken", - "weight": 28, + "weight": 29, "cookies": false, "type": "", "deprecated": false, @@ -3181,9 +3058,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3246,7 +3120,7 @@ }, "x-appwrite": { "method": "createVerification", - "weight": 40, + "weight": 41, "cookies": false, "type": "", "deprecated": false, @@ -3261,9 +3135,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3319,7 +3190,7 @@ }, "x-appwrite": { "method": "updateVerification", - "weight": 41, + "weight": 42, "cookies": false, "type": "", "deprecated": false, @@ -3334,9 +3205,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3401,7 +3269,7 @@ }, "x-appwrite": { "method": "createPhoneVerification", - "weight": 42, + "weight": 43, "cookies": false, "type": "", "deprecated": false, @@ -3419,9 +3287,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3457,7 +3322,7 @@ }, "x-appwrite": { "method": "updatePhoneVerification", - "weight": 43, + "weight": 44, "cookies": false, "type": "", "deprecated": false, @@ -3472,9 +3337,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3539,7 +3401,7 @@ }, "x-appwrite": { "method": "getBrowser", - "weight": 60, + "weight": 61, "cookies": false, "type": "location", "deprecated": false, @@ -3555,9 +3417,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3668,7 +3527,7 @@ }, "x-appwrite": { "method": "getCreditCard", - "weight": 59, + "weight": 60, "cookies": false, "type": "location", "deprecated": false, @@ -3684,9 +3543,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3701,7 +3557,7 @@ "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.", + "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", @@ -3721,7 +3577,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3740,7 +3597,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ], "in": "path" }, @@ -3801,7 +3659,7 @@ }, "x-appwrite": { "method": "getFavicon", - "weight": 63, + "weight": 64, "cookies": false, "type": "location", "deprecated": false, @@ -3817,9 +3675,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3868,7 +3723,7 @@ }, "x-appwrite": { "method": "getFlag", - "weight": 61, + "weight": 62, "cookies": false, "type": "location", "deprecated": false, @@ -3884,9 +3739,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4359,7 +4211,7 @@ }, "x-appwrite": { "method": "getImage", - "weight": 62, + "weight": 63, "cookies": false, "type": "location", "deprecated": false, @@ -4375,9 +4227,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4446,7 +4295,7 @@ }, "x-appwrite": { "method": "getInitials", - "weight": 65, + "weight": 66, "cookies": false, "type": "location", "deprecated": false, @@ -4462,9 +4311,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4541,7 +4387,7 @@ }, "x-appwrite": { "method": "getQR", - "weight": 64, + "weight": 65, "cookies": false, "type": "location", "deprecated": false, @@ -4557,9 +4403,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4636,7 +4479,7 @@ }, "x-appwrite": { "method": "listDocuments", - "weight": 109, + "weight": 110, "cookies": false, "type": "", "deprecated": false, @@ -4652,9 +4495,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4709,7 +4549,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -4720,7 +4560,7 @@ }, "x-appwrite": { "method": "createDocument", - "weight": 108, + "weight": 109, "cookies": false, "type": "", "deprecated": false, @@ -4736,9 +4576,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4828,7 +4665,7 @@ }, "x-appwrite": { "method": "getDocument", - "weight": 110, + "weight": 111, "cookies": false, "type": "", "deprecated": false, @@ -4844,9 +4681,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4920,7 +4754,7 @@ }, "x-appwrite": { "method": "updateDocument", - "weight": 112, + "weight": 113, "cookies": false, "type": "", "deprecated": false, @@ -4936,9 +4770,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5019,7 +4850,7 @@ }, "x-appwrite": { "method": "deleteDocument", - "weight": 113, + "weight": 114, "cookies": false, "type": "", "deprecated": false, @@ -5035,9 +4866,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5101,12 +4929,12 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 306, + "weight": 384, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-executions.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -5117,9 +4945,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5151,15 +4976,6 @@ }, "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" } ] }, @@ -5186,12 +5002,12 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 305, + "weight": 382, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -5202,9 +5018,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5307,12 +5120,12 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 307, + "weight": 383, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -5323,9 +5136,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5381,7 +5191,7 @@ }, "x-appwrite": { "method": "query", - "weight": 331, + "weight": 303, "cookies": false, "type": "graphql", "deprecated": false, @@ -5397,9 +5207,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5457,7 +5264,7 @@ }, "x-appwrite": { "method": "mutation", - "weight": 330, + "weight": 302, "cookies": false, "type": "graphql", "deprecated": false, @@ -5473,9 +5280,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5533,7 +5337,7 @@ }, "x-appwrite": { "method": "get", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -5549,9 +5353,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5589,7 +5390,7 @@ }, "x-appwrite": { "method": "listCodes", - "weight": 118, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -5605,9 +5406,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5645,7 +5443,7 @@ }, "x-appwrite": { "method": "listContinents", - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -5661,9 +5459,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5701,7 +5496,7 @@ }, "x-appwrite": { "method": "listCountries", - "weight": 119, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -5717,9 +5512,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5757,7 +5549,7 @@ }, "x-appwrite": { "method": "listCountriesEU", - "weight": 120, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -5773,9 +5565,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5813,7 +5602,7 @@ }, "x-appwrite": { "method": "listCountriesPhones", - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -5829,9 +5618,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -5869,7 +5655,7 @@ }, "x-appwrite": { "method": "listCurrencies", - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -5885,9 +5671,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5925,7 +5708,7 @@ }, "x-appwrite": { "method": "listLanguages", - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -5941,9 +5724,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -5981,7 +5761,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -5998,9 +5778,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6056,9 +5833,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -6070,7 +5845,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -6087,9 +5862,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6145,7 +5917,7 @@ }, "x-appwrite": { "method": "listFiles", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -6161,9 +5933,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6230,7 +5999,7 @@ }, "x-appwrite": { "method": "createFile", - "weight": 207, + "weight": 208, "cookies": false, "type": "upload", "deprecated": false, @@ -6246,9 +6015,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6324,7 +6090,7 @@ }, "x-appwrite": { "method": "getFile", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -6340,9 +6106,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6396,7 +6159,7 @@ }, "x-appwrite": { "method": "updateFile", - "weight": 214, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -6412,9 +6175,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6487,7 +6247,7 @@ }, "x-appwrite": { "method": "deleteFile", - "weight": 215, + "weight": 216, "cookies": false, "type": "", "deprecated": false, @@ -6503,9 +6263,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6561,7 +6318,7 @@ }, "x-appwrite": { "method": "getFileDownload", - "weight": 211, + "weight": 212, "cookies": false, "type": "location", "deprecated": false, @@ -6577,9 +6334,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6635,7 +6389,7 @@ }, "x-appwrite": { "method": "getFilePreview", - "weight": 210, + "weight": 211, "cookies": false, "type": "location", "deprecated": false, @@ -6651,9 +6405,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6802,6 +6553,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -6836,7 +6588,7 @@ }, "x-appwrite": { "method": "getFileView", - "weight": 212, + "weight": 213, "cookies": false, "type": "location", "deprecated": false, @@ -6852,9 +6604,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6910,7 +6659,7 @@ }, "x-appwrite": { "method": "list", - "weight": 219, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -6926,9 +6675,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6987,7 +6733,7 @@ }, "x-appwrite": { "method": "create", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -7003,9 +6749,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7081,7 +6824,7 @@ }, "x-appwrite": { "method": "get", - "weight": 220, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -7097,9 +6840,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7145,7 +6885,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -7161,9 +6901,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7222,7 +6959,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -7238,9 +6975,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7288,7 +7022,7 @@ }, "x-appwrite": { "method": "listMemberships", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -7304,9 +7038,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7329,7 +7060,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: userId, teamId, invited, joined, confirm", + "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", @@ -7373,7 +7104,7 @@ }, "x-appwrite": { "method": "createMembership", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -7389,9 +7120,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7490,7 +7218,7 @@ }, "x-appwrite": { "method": "getMembership", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -7506,9 +7234,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7562,7 +7287,7 @@ }, "x-appwrite": { "method": "updateMembership", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -7578,9 +7303,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7650,7 +7372,7 @@ }, "x-appwrite": { "method": "deleteMembership", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -7666,9 +7388,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7724,7 +7443,7 @@ }, "x-appwrite": { "method": "updateMembershipStatus", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -7739,9 +7458,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7822,7 +7538,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -7837,9 +7553,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7885,7 +7598,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -7900,9 +7613,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7998,6 +7708,11 @@ "description": "The Users service allows you to manage your project users.", "x-globalAttributes": [] }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, { "name": "functions", "description": "The Functions Service allows you view, create and manage your Cloud Functions.", @@ -9613,7 +9328,7 @@ }, "duration": { "type": "number", - "description": "Function execution duration in seconds.", + "description": "Resource(function\/site) execution duration in seconds.", "x-example": 0.4, "format": "double" }, diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index c7b6bac2d4..76f1152287 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.6.0", + "version": "1.7.0", "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", @@ -99,7 +99,7 @@ }, "x-appwrite": { "method": "get", - "weight": 9, + "weight": 10, "cookies": false, "type": "", "deprecated": false, @@ -114,9 +114,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -151,7 +148,7 @@ }, "x-appwrite": { "method": "create", - "weight": 8, + "weight": 9, "cookies": false, "type": "", "deprecated": false, @@ -166,9 +163,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -237,7 +231,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 10, + "weight": 11, "cookies": false, "type": "", "deprecated": false, @@ -251,9 +245,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -289,7 +280,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 34, + "weight": 35, "cookies": false, "type": "", "deprecated": false, @@ -304,9 +295,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -370,7 +358,7 @@ }, "x-appwrite": { "method": "listIdentities", - "weight": 57, + "weight": 58, "cookies": false, "type": "", "deprecated": false, @@ -385,9 +373,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -433,7 +418,7 @@ }, "x-appwrite": { "method": "deleteIdentity", - "weight": 58, + "weight": 59, "cookies": false, "type": "", "deprecated": false, @@ -448,9 +433,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -497,7 +479,7 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 29, + "weight": 30, "cookies": false, "type": "", "deprecated": false, @@ -512,9 +494,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -550,7 +529,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 31, + "weight": 32, "cookies": false, "type": "", "deprecated": false, @@ -565,9 +544,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -618,7 +594,7 @@ }, "x-appwrite": { "method": "updateMFA", - "weight": 44, + "weight": 45, "cookies": false, "type": "", "deprecated": false, @@ -633,9 +609,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -692,7 +665,7 @@ }, "x-appwrite": { "method": "createMfaAuthenticator", - "weight": 46, + "weight": 47, "cookies": false, "type": "", "deprecated": false, @@ -707,9 +680,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -759,7 +729,7 @@ }, "x-appwrite": { "method": "updateMfaAuthenticator", - "weight": 47, + "weight": 48, "cookies": false, "type": "", "deprecated": false, @@ -774,9 +744,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -839,7 +806,7 @@ }, "x-appwrite": { "method": "deleteMfaAuthenticator", - "weight": 51, + "weight": 52, "cookies": false, "type": "", "deprecated": false, @@ -854,9 +821,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -908,7 +872,7 @@ }, "x-appwrite": { "method": "createMfaChallenge", - "weight": 52, + "weight": 53, "cookies": false, "type": "", "deprecated": false, @@ -923,9 +887,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -970,19 +931,24 @@ "consumes": [ "application\/json" ], - "produces": [], + "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": { - "204": { - "description": "No content" + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } } }, "x-appwrite": { "method": "updateMfaChallenge", - "weight": 53, + "weight": 54, "cookies": false, "type": "", "deprecated": false, @@ -997,9 +963,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1063,7 +1026,7 @@ }, "x-appwrite": { "method": "listMfaFactors", - "weight": 45, + "weight": 46, "cookies": false, "type": "", "deprecated": false, @@ -1078,9 +1041,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1117,7 +1077,7 @@ }, "x-appwrite": { "method": "getMfaRecoveryCodes", - "weight": 50, + "weight": 51, "cookies": false, "type": "", "deprecated": false, @@ -1132,9 +1092,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1169,7 +1126,7 @@ }, "x-appwrite": { "method": "createMfaRecoveryCodes", - "weight": 48, + "weight": 49, "cookies": false, "type": "", "deprecated": false, @@ -1184,9 +1141,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1221,7 +1175,7 @@ }, "x-appwrite": { "method": "updateMfaRecoveryCodes", - "weight": 49, + "weight": 50, "cookies": false, "type": "", "deprecated": false, @@ -1236,9 +1190,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1275,7 +1226,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 32, + "weight": 33, "cookies": false, "type": "", "deprecated": false, @@ -1290,9 +1241,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1349,7 +1297,7 @@ }, "x-appwrite": { "method": "updatePassword", - "weight": 33, + "weight": 34, "cookies": false, "type": "", "deprecated": false, @@ -1364,9 +1312,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1429,7 +1374,7 @@ }, "x-appwrite": { "method": "updatePhone", - "weight": 35, + "weight": 36, "cookies": false, "type": "", "deprecated": false, @@ -1444,9 +1389,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1510,7 +1452,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 30, + "weight": 31, "cookies": false, "type": "", "deprecated": false, @@ -1525,9 +1467,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1562,7 +1501,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 36, + "weight": 37, "cookies": false, "type": "", "deprecated": false, @@ -1577,9 +1516,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1636,7 +1572,7 @@ }, "x-appwrite": { "method": "createRecovery", - "weight": 38, + "weight": 39, "cookies": false, "type": "", "deprecated": false, @@ -1654,9 +1590,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1718,7 +1651,7 @@ }, "x-appwrite": { "method": "updateRecovery", - "weight": 39, + "weight": 40, "cookies": false, "type": "", "deprecated": false, @@ -1733,9 +1666,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1806,7 +1736,7 @@ }, "x-appwrite": { "method": "listSessions", - "weight": 11, + "weight": 12, "cookies": false, "type": "", "deprecated": false, @@ -1821,9 +1751,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1853,7 +1780,7 @@ }, "x-appwrite": { "method": "deleteSessions", - "weight": 12, + "weight": 13, "cookies": false, "type": "", "deprecated": false, @@ -1868,9 +1795,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1907,7 +1831,7 @@ }, "x-appwrite": { "method": "createAnonymousSession", - "weight": 17, + "weight": 18, "cookies": false, "type": "", "deprecated": false, @@ -1922,9 +1846,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1960,7 +1881,7 @@ }, "x-appwrite": { "method": "createEmailPasswordSession", - "weight": 16, + "weight": 17, "cookies": false, "type": "", "deprecated": false, @@ -1975,9 +1896,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2040,7 +1958,7 @@ }, "x-appwrite": { "method": "updateMagicURLSession", - "weight": 26, + "weight": 27, "cookies": false, "type": "", "deprecated": true, @@ -2055,9 +1973,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2117,7 +2032,7 @@ }, "x-appwrite": { "method": "createOAuth2Session", - "weight": 19, + "weight": 20, "cookies": false, "type": "webAuth", "deprecated": false, @@ -2132,9 +2047,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2255,7 +2167,7 @@ }, "x-appwrite": { "method": "updatePhoneSession", - "weight": 27, + "weight": 28, "cookies": false, "type": "", "deprecated": true, @@ -2270,9 +2182,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2335,7 +2244,7 @@ }, "x-appwrite": { "method": "createSession", - "weight": 18, + "weight": 19, "cookies": false, "type": "", "deprecated": false, @@ -2350,9 +2259,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2415,7 +2321,7 @@ }, "x-appwrite": { "method": "getSession", - "weight": 13, + "weight": 14, "cookies": false, "type": "", "deprecated": false, @@ -2430,9 +2336,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2477,7 +2380,7 @@ }, "x-appwrite": { "method": "updateSession", - "weight": 15, + "weight": 16, "cookies": false, "type": "", "deprecated": false, @@ -2492,9 +2395,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2534,7 +2434,7 @@ }, "x-appwrite": { "method": "deleteSession", - "weight": 14, + "weight": 15, "cookies": false, "type": "", "deprecated": false, @@ -2549,9 +2449,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2598,7 +2495,7 @@ }, "x-appwrite": { "method": "updateStatus", - "weight": 37, + "weight": 38, "cookies": false, "type": "", "deprecated": false, @@ -2613,9 +2510,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2641,7 +2535,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2652,12 +2546,12 @@ }, "x-appwrite": { "method": "createPushTarget", - "weight": 54, + "weight": 55, "cookies": false, "type": "", "deprecated": false, "demo": "account\/create-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2666,9 +2560,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2726,7 +2617,7 @@ "tags": [ "account" ], - "description": "", + "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", @@ -2737,12 +2628,12 @@ }, "x-appwrite": { "method": "updatePushTarget", - "weight": 55, + "weight": 56, "cookies": false, "type": "", "deprecated": false, "demo": "account\/update-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2751,9 +2642,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2798,13 +2686,11 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "account" ], - "description": "", + "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" @@ -2812,12 +2698,12 @@ }, "x-appwrite": { "method": "deletePushTarget", - "weight": 56, + "weight": 57, "cookies": false, "type": "", "deprecated": false, "demo": "account\/delete-push-target.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -2826,9 +2712,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2874,7 +2757,7 @@ }, "x-appwrite": { "method": "createEmailToken", - "weight": 25, + "weight": 26, "cookies": false, "type": "", "deprecated": false, @@ -2889,9 +2772,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2949,7 +2829,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2960,7 +2840,7 @@ }, "x-appwrite": { "method": "createMagicURLToken", - "weight": 24, + "weight": 25, "cookies": false, "type": "", "deprecated": false, @@ -2978,9 +2858,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3052,7 +2929,7 @@ }, "x-appwrite": { "method": "createOAuth2Token", - "weight": 23, + "weight": 24, "cookies": false, "type": "webAuth", "deprecated": false, @@ -3067,9 +2944,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3190,7 +3064,7 @@ }, "x-appwrite": { "method": "createPhoneToken", - "weight": 28, + "weight": 29, "cookies": false, "type": "", "deprecated": false, @@ -3208,9 +3082,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3273,7 +3144,7 @@ }, "x-appwrite": { "method": "createVerification", - "weight": 40, + "weight": 41, "cookies": false, "type": "", "deprecated": false, @@ -3288,9 +3159,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3345,7 +3213,7 @@ }, "x-appwrite": { "method": "updateVerification", - "weight": 41, + "weight": 42, "cookies": false, "type": "", "deprecated": false, @@ -3360,9 +3228,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3426,7 +3291,7 @@ }, "x-appwrite": { "method": "createPhoneVerification", - "weight": 42, + "weight": 43, "cookies": false, "type": "", "deprecated": false, @@ -3444,9 +3309,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3481,7 +3343,7 @@ }, "x-appwrite": { "method": "updatePhoneVerification", - "weight": 43, + "weight": 44, "cookies": false, "type": "", "deprecated": false, @@ -3496,9 +3358,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3562,7 +3421,7 @@ }, "x-appwrite": { "method": "getBrowser", - "weight": 60, + "weight": 61, "cookies": false, "type": "location", "deprecated": false, @@ -3578,9 +3437,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3691,7 +3547,7 @@ }, "x-appwrite": { "method": "getCreditCard", - "weight": 59, + "weight": 60, "cookies": false, "type": "location", "deprecated": false, @@ -3707,9 +3563,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3724,7 +3577,7 @@ "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.", + "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", @@ -3744,7 +3597,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3763,7 +3617,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ], "in": "path" }, @@ -3824,7 +3679,7 @@ }, "x-appwrite": { "method": "getFavicon", - "weight": 63, + "weight": 64, "cookies": false, "type": "location", "deprecated": false, @@ -3840,9 +3695,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -3891,7 +3743,7 @@ }, "x-appwrite": { "method": "getFlag", - "weight": 61, + "weight": 62, "cookies": false, "type": "location", "deprecated": false, @@ -3907,9 +3759,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4382,7 +4231,7 @@ }, "x-appwrite": { "method": "getImage", - "weight": 62, + "weight": 63, "cookies": false, "type": "location", "deprecated": false, @@ -4398,9 +4247,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4469,7 +4315,7 @@ }, "x-appwrite": { "method": "getInitials", - "weight": 65, + "weight": 66, "cookies": false, "type": "location", "deprecated": false, @@ -4485,9 +4331,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4564,7 +4407,7 @@ }, "x-appwrite": { "method": "getQR", - "weight": 64, + "weight": 65, "cookies": false, "type": "location", "deprecated": false, @@ -4580,9 +4423,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4648,7 +4488,7 @@ "tags": [ "assistant" ], - "description": "", + "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", @@ -4659,7 +4499,7 @@ }, "x-appwrite": { "method": "chat", - "weight": 333, + "weight": 305, "cookies": false, "type": "", "deprecated": false, @@ -4673,9 +4513,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4707,6 +4544,73 @@ ] } }, + "\/console\/resources": { + "get": { + "summary": "Check resource ID availability", + "operationId": "consoleGetResource", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "console" + ], + "description": "Check if a resource ID is available.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "getResource", + "weight": 424, + "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", @@ -4731,7 +4635,7 @@ }, "x-appwrite": { "method": "variables", - "weight": 332, + "weight": 304, "cookies": false, "type": "", "deprecated": false, @@ -4745,9 +4649,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4783,7 +4684,7 @@ }, "x-appwrite": { "method": "list", - "weight": 70, + "weight": 71, "cookies": false, "type": "", "deprecated": false, @@ -4797,9 +4698,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4857,7 +4755,7 @@ }, "x-appwrite": { "method": "create", - "weight": 69, + "weight": 70, "cookies": false, "type": "", "deprecated": false, @@ -4871,9 +4769,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -4932,7 +4827,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -4943,12 +4838,12 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 114, + "weight": 115, "cookies": false, "type": "", "deprecated": false, "demo": "databases\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -4957,9 +4852,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5017,7 +4909,7 @@ }, "x-appwrite": { "method": "get", - "weight": 71, + "weight": 72, "cookies": false, "type": "", "deprecated": false, @@ -5031,9 +4923,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5078,7 +4967,7 @@ }, "x-appwrite": { "method": "update", - "weight": 73, + "weight": 74, "cookies": false, "type": "", "deprecated": false, @@ -5092,9 +4981,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5158,7 +5044,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 74, + "weight": 75, "cookies": false, "type": "", "deprecated": false, @@ -5172,9 +5058,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5221,7 +5104,7 @@ }, "x-appwrite": { "method": "listCollections", - "weight": 76, + "weight": 77, "cookies": false, "type": "", "deprecated": false, @@ -5235,9 +5118,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5303,7 +5183,7 @@ }, "x-appwrite": { "method": "createCollection", - "weight": 75, + "weight": 76, "cookies": false, "type": "", "deprecated": false, @@ -5317,9 +5197,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5412,7 +5289,7 @@ }, "x-appwrite": { "method": "getCollection", - "weight": 77, + "weight": 78, "cookies": false, "type": "", "deprecated": false, @@ -5426,9 +5303,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5481,7 +5355,7 @@ }, "x-appwrite": { "method": "updateCollection", - "weight": 79, + "weight": 80, "cookies": false, "type": "", "deprecated": false, @@ -5495,9 +5369,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5584,7 +5455,7 @@ }, "x-appwrite": { "method": "deleteCollection", - "weight": 80, + "weight": 81, "cookies": false, "type": "", "deprecated": false, @@ -5598,9 +5469,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5655,7 +5523,7 @@ }, "x-appwrite": { "method": "listAttributes", - "weight": 91, + "weight": 92, "cookies": false, "type": "", "deprecated": false, @@ -5669,9 +5537,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5738,7 +5603,7 @@ }, "x-appwrite": { "method": "createBooleanAttribute", - "weight": 88, + "weight": 89, "cookies": false, "type": "", "deprecated": false, @@ -5752,9 +5617,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5829,7 +5691,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5844,7 +5708,7 @@ }, "x-appwrite": { "method": "updateBooleanAttribute", - "weight": 100, + "weight": 101, "cookies": false, "type": "", "deprecated": false, @@ -5858,9 +5722,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -5954,7 +5815,7 @@ }, "x-appwrite": { "method": "createDatetimeAttribute", - "weight": 89, + "weight": 90, "cookies": false, "type": "", "deprecated": false, @@ -5968,9 +5829,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6045,7 +5903,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6060,7 +5920,7 @@ }, "x-appwrite": { "method": "updateDatetimeAttribute", - "weight": 101, + "weight": 102, "cookies": false, "type": "", "deprecated": false, @@ -6074,9 +5934,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6170,7 +6027,7 @@ }, "x-appwrite": { "method": "createEmailAttribute", - "weight": 82, + "weight": 83, "cookies": false, "type": "", "deprecated": false, @@ -6184,9 +6041,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6261,7 +6115,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6276,7 +6132,7 @@ }, "x-appwrite": { "method": "updateEmailAttribute", - "weight": 94, + "weight": 95, "cookies": false, "type": "", "deprecated": false, @@ -6290,9 +6146,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6386,7 +6239,7 @@ }, "x-appwrite": { "method": "createEnumAttribute", - "weight": 83, + "weight": 84, "cookies": false, "type": "", "deprecated": false, @@ -6400,9 +6253,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6487,7 +6337,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6502,7 +6354,7 @@ }, "x-appwrite": { "method": "updateEnumAttribute", - "weight": 95, + "weight": 96, "cookies": false, "type": "", "deprecated": false, @@ -6516,9 +6368,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6622,7 +6471,7 @@ }, "x-appwrite": { "method": "createFloatAttribute", - "weight": 87, + "weight": 88, "cookies": false, "type": "", "deprecated": false, @@ -6636,9 +6485,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6725,7 +6571,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6740,7 +6588,7 @@ }, "x-appwrite": { "method": "updateFloatAttribute", - "weight": 99, + "weight": 100, "cookies": false, "type": "", "deprecated": false, @@ -6754,9 +6602,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6831,8 +6676,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6864,7 +6707,7 @@ }, "x-appwrite": { "method": "createIntegerAttribute", - "weight": 86, + "weight": 87, "cookies": false, "type": "", "deprecated": false, @@ -6878,9 +6721,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -6967,7 +6807,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6982,7 +6824,7 @@ }, "x-appwrite": { "method": "updateIntegerAttribute", - "weight": 98, + "weight": 99, "cookies": false, "type": "", "deprecated": false, @@ -6996,9 +6838,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7073,8 +6912,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -7106,7 +6943,7 @@ }, "x-appwrite": { "method": "createIpAttribute", - "weight": 84, + "weight": 85, "cookies": false, "type": "", "deprecated": false, @@ -7120,9 +6957,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7197,7 +7031,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7212,7 +7048,7 @@ }, "x-appwrite": { "method": "updateIpAttribute", - "weight": 96, + "weight": 97, "cookies": false, "type": "", "deprecated": false, @@ -7226,9 +7062,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7322,7 +7155,7 @@ }, "x-appwrite": { "method": "createRelationshipAttribute", - "weight": 90, + "weight": 91, "cookies": false, "type": "", "deprecated": false, @@ -7336,9 +7169,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7457,7 +7287,7 @@ }, "x-appwrite": { "method": "createStringAttribute", - "weight": 81, + "weight": 82, "cookies": false, "type": "", "deprecated": false, @@ -7471,9 +7301,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7561,7 +7388,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7576,7 +7405,7 @@ }, "x-appwrite": { "method": "updateStringAttribute", - "weight": 93, + "weight": 94, "cookies": false, "type": "", "deprecated": false, @@ -7590,9 +7419,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7692,7 +7518,7 @@ }, "x-appwrite": { "method": "createUrlAttribute", - "weight": 85, + "weight": 86, "cookies": false, "type": "", "deprecated": false, @@ -7706,9 +7532,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7783,7 +7606,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7798,7 +7623,7 @@ }, "x-appwrite": { "method": "updateUrlAttribute", - "weight": 97, + "weight": 98, "cookies": false, "type": "", "deprecated": false, @@ -7812,9 +7637,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -7939,7 +7761,7 @@ }, "x-appwrite": { "method": "getAttribute", - "weight": 92, + "weight": 93, "cookies": false, "type": "", "deprecated": false, @@ -7953,9 +7775,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8010,7 +7829,7 @@ }, "x-appwrite": { "method": "deleteAttribute", - "weight": 103, + "weight": 104, "cookies": false, "type": "", "deprecated": false, @@ -8024,9 +7843,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8071,7 +7887,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -8086,7 +7904,7 @@ }, "x-appwrite": { "method": "updateRelationshipAttribute", - "weight": 102, + "weight": 103, "cookies": false, "type": "", "deprecated": false, @@ -8100,9 +7918,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8192,7 +8007,7 @@ }, "x-appwrite": { "method": "listDocuments", - "weight": 109, + "weight": 110, "cookies": false, "type": "", "deprecated": false, @@ -8208,9 +8023,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8265,7 +8077,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -8276,7 +8088,7 @@ }, "x-appwrite": { "method": "createDocument", - "weight": 108, + "weight": 109, "cookies": false, "type": "", "deprecated": false, @@ -8292,9 +8104,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8384,7 +8193,7 @@ }, "x-appwrite": { "method": "getDocument", - "weight": 110, + "weight": 111, "cookies": false, "type": "", "deprecated": false, @@ -8400,9 +8209,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8476,7 +8282,7 @@ }, "x-appwrite": { "method": "updateDocument", - "weight": 112, + "weight": 113, "cookies": false, "type": "", "deprecated": false, @@ -8492,9 +8298,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8575,7 +8378,7 @@ }, "x-appwrite": { "method": "deleteDocument", - "weight": 113, + "weight": 114, "cookies": false, "type": "", "deprecated": false, @@ -8591,9 +8394,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8657,7 +8457,7 @@ }, "x-appwrite": { "method": "listDocumentLogs", - "weight": 111, + "weight": 112, "cookies": false, "type": "", "deprecated": false, @@ -8671,9 +8471,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8747,7 +8544,7 @@ }, "x-appwrite": { "method": "listIndexes", - "weight": 105, + "weight": 106, "cookies": false, "type": "", "deprecated": false, @@ -8761,9 +8558,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8828,7 +8622,7 @@ }, "x-appwrite": { "method": "createIndex", - "weight": 104, + "weight": 105, "cookies": false, "type": "", "deprecated": false, @@ -8842,9 +8636,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -8950,7 +8741,7 @@ }, "x-appwrite": { "method": "getIndex", - "weight": 106, + "weight": 107, "cookies": false, "type": "", "deprecated": false, @@ -8964,9 +8755,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9021,7 +8809,7 @@ }, "x-appwrite": { "method": "deleteIndex", - "weight": 107, + "weight": 108, "cookies": false, "type": "", "deprecated": false, @@ -9035,9 +8823,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9099,7 +8884,7 @@ }, "x-appwrite": { "method": "listCollectionLogs", - "weight": 78, + "weight": 79, "cookies": false, "type": "", "deprecated": false, @@ -9113,9 +8898,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9170,7 +8952,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -9181,12 +8963,12 @@ }, "x-appwrite": { "method": "getCollectionUsage", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, "demo": "databases\/get-collection-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -9195,9 +8977,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9271,7 +9050,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 72, + "weight": 73, "cookies": false, "type": "", "deprecated": false, @@ -9285,9 +9064,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9334,7 +9110,7 @@ "tags": [ "databases" ], - "description": "", + "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", @@ -9345,12 +9121,12 @@ }, "x-appwrite": { "method": "getDatabaseUsage", - "weight": 115, + "weight": 116, "cookies": false, "type": "", "deprecated": false, "demo": "databases\/get-database-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -9359,9 +9135,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9427,12 +9200,12 @@ }, "x-appwrite": { "method": "list", - "weight": 289, + "weight": 368, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/list-functions.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}", @@ -9441,9 +9214,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9457,7 +9227,7 @@ "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, deployment, schedule, scheduleNext, schedulePrevious, timeout, entrypoint, commands, installationId", + "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", @@ -9501,12 +9271,12 @@ }, "x-appwrite": { "method": "create", - "weight": 288, + "weight": 365, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-function.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}", @@ -9515,9 +9285,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9574,6 +9341,7 @@ "python-3.11", "python-3.12", "python-ml-3.11", + "python-ml-3.12", "deno-1.21", "deno-1.24", "deno-1.35", @@ -9584,6 +9352,7 @@ "dart-2.16", "dart-2.17", "dart-2.18", + "dart-2.19", "dart-3.0", "dart-3.1", "dart-3.3", @@ -9610,7 +9379,10 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29" ], "x-enum-name": null, "x-enum-keys": [] @@ -9653,7 +9425,7 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "default": true, "x-example": false }, @@ -9708,30 +9480,6 @@ "default": "", "x-example": "<PROVIDER_ROOT_DIRECTORY>" }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "default": "", - "x-example": "<TEMPLATE_REPOSITORY>" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "default": "", - "x-example": "<TEMPLATE_OWNER>" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "default": "", - "x-example": "<TEMPLATE_ROOT_DIRECTORY>" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "default": "", - "x-example": "<TEMPLATE_VERSION>" - }, "specification": { "type": "string", "description": "Runtime specification for the function and builds.", @@ -9773,23 +9521,20 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 290, + "weight": 370, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-runtimes.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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": "functions.read", + "scope": "public", "platforms": [ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9804,7 +9549,7 @@ }, "\/functions\/specifications": { "get": { - "summary": "List available function runtime specifications", + "summary": "List specifications", "operationId": "functionsListSpecifications", "consumes": [ "application\/json" @@ -9815,7 +9560,7 @@ "tags": [ "functions" ], - "description": "List allowed function specifications for this instance.\n", + "description": "List allowed function specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -9826,12 +9571,12 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 291, + "weight": 371, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-specifications.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9841,9 +9586,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9858,7 +9600,7 @@ }, "\/functions\/templates": { "get": { - "summary": "List function templates", + "summary": "List templates", "operationId": "functionsListTemplates", "consumes": [ "application\/json" @@ -9880,12 +9622,12 @@ }, "x-appwrite": { "method": "listTemplates", - "weight": 314, + "weight": 394, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-templates.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9894,9 +9636,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -9978,12 +9717,12 @@ }, "x-appwrite": { "method": "getTemplate", - "weight": 315, + "weight": 393, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9992,9 +9731,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10019,7 +9755,7 @@ "\/functions\/usage": { "get": { "summary": "Get functions usage", - "operationId": "functionsGetUsage", + "operationId": "functionsListUsage", "consumes": [ "application\/json" ], @@ -10029,7 +9765,7 @@ "tags": [ "functions" ], - "description": "", + "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", @@ -10039,13 +9775,13 @@ } }, "x-appwrite": { - "method": "getUsage", - "weight": 294, + "method": "listUsage", + "weight": 387, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -10054,9 +9790,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10114,12 +9847,12 @@ }, "x-appwrite": { "method": "get", - "weight": 292, + "weight": 366, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-function.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}", @@ -10128,9 +9861,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10175,12 +9905,12 @@ }, "x-appwrite": { "method": "update", - "weight": 295, + "weight": 367, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/update.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-function.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}", @@ -10189,9 +9919,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10250,6 +9977,7 @@ "python-3.11", "python-3.12", "python-ml-3.11", + "python-ml-3.12", "deno-1.21", "deno-1.24", "deno-1.35", @@ -10260,6 +9988,7 @@ "dart-2.16", "dart-2.17", "dart-2.18", + "dart-2.19", "dart-3.0", "dart-3.1", "dart-3.3", @@ -10286,7 +10015,10 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29" ], "x-enum-name": null, "x-enum-keys": [] @@ -10329,7 +10061,7 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "default": true, "x-example": false }, @@ -10417,12 +10149,12 @@ }, "x-appwrite": { "method": "delete", - "weight": 298, + "weight": 369, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/delete-function.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}", @@ -10431,9 +10163,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10456,6 +10185,84 @@ ] } }, + "\/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", + "weight": 374, + "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", @@ -10469,7 +10276,7 @@ "tags": [ "functions" ], - "description": "Get a list of all the project's code deployments. You can use the query params to filter your results.", + "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", @@ -10480,12 +10287,12 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 300, + "weight": 375, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-deployments.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10494,9 +10301,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10518,7 +10322,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: size, buildId, activate, entrypoint, commands, type, size", + "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", @@ -10562,12 +10366,12 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 299, + "weight": 372, "cookies": false, "type": "upload", "deprecated": false, "demo": "functions\/create-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10576,9 +10380,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10632,10 +10433,10 @@ ] } }, - "\/functions\/{functionId}\/deployments\/{deploymentId}": { - "get": { - "summary": "Get deployment", - "operationId": "functionsGetDeployment", + "\/functions\/{functionId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "functionsCreateDuplicateDeployment", "consumes": [ "application\/json" ], @@ -10645,9 +10446,9 @@ "tags": [ "functions" ], - "description": "Get a code deployment by its unique ID.", + "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": { - "200": { + "202": { "description": "Deployment", "schema": { "$ref": "#\/definitions\/deployment" @@ -10655,24 +10456,21 @@ } }, "x-appwrite": { - "method": "getDeployment", - "weight": 301, + "method": "createDuplicateDeployment", + "weight": 380, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/get-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-deployment.md", + "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.read", + "scope": "functions.write", "platforms": [ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10693,18 +10491,36 @@ "in": "path" }, { - "name": "deploymentId", - "description": "Deployment ID.", - "required": true, - "type": "string", - "x-example": "<DEPLOYMENT_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" + ] + } } ] - }, - "patch": { - "summary": "Update deployment", - "operationId": "functionsUpdateDeployment", + } + }, + "\/functions\/{functionId}\/deployments\/template": { + "post": { + "summary": "Create template deployment", + "operationId": "functionsCreateTemplateDeployment", "consumes": [ "application\/json" ], @@ -10714,23 +10530,23 @@ "tags": [ "functions" ], - "description": "Update the function code deployment ID using the unique function ID. Use this endpoint to switch the code deployment that should be executed by the execution endpoint.", + "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": { - "200": { - "description": "Function", + "202": { + "description": "Deployment", "schema": { - "$ref": "#\/definitions\/function" + "$ref": "#\/definitions\/deployment" } } }, "x-appwrite": { - "method": "updateDeployment", - "weight": 297, + "method": "createTemplateDeployment", + "weight": 377, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/update-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-function-deployment.md", + "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}", @@ -10739,9 +10555,208 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", + "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", + "weight": 378, + "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": [ + "application\/json" + ], + "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", + "weight": 373, + "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": [] } @@ -10789,12 +10804,12 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 302, + "weight": 376, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10803,159 +10818,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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}\/build": { - "post": { - "summary": "Rebuild deployment", - "operationId": "functionsCreateBuild", - "consumes": [ - "application\/json" - ], - "produces": [], - "tags": [ - "functions" - ], - "description": "", - "responses": { - "204": { - "description": "No content" - } - }, - "x-appwrite": { - "method": "createBuild", - "weight": 303, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "functions.write", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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" - }, - { - "name": "payload", - "in": "body", - "schema": { - "type": "object", - "properties": { - "buildId": { - "type": "string", - "description": "Build unique ID.", - "default": "", - "x-example": "<BUILD_ID>" - } - } - } - } - ] - }, - "patch": { - "summary": "Cancel deployment", - "operationId": "functionsUpdateDeploymentBuild", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "functions" - ], - "description": "", - "responses": { - "200": { - "description": "Build", - "schema": { - "$ref": "#\/definitions\/build" - } - } - }, - "x-appwrite": { - "method": "updateDeploymentBuild", - "weight": 304, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "functions.write", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -10999,7 +10861,7 @@ "tags": [ "functions" ], - "description": "Get a Deployment's contents by its unique ID. This endpoint supports range requests for partial or streaming file download.", + "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", @@ -11010,12 +10872,12 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 296, + "weight": 379, "cookies": false, "type": "location", "deprecated": false, "demo": "functions\/get-deployment-download.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11025,9 +10887,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11039,6 +10898,89 @@ "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", + "weight": 381, + "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", @@ -11083,12 +11025,12 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 306, + "weight": 384, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-executions.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11099,9 +11041,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11133,15 +11072,6 @@ }, "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" } ] }, @@ -11168,12 +11098,12 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 305, + "weight": 382, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11184,9 +11114,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11289,12 +11216,12 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 307, + "weight": 383, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11305,9 +11232,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11348,7 +11272,7 @@ "tags": [ "functions" ], - "description": "Delete a function execution by its unique ID.\n", + "description": "Delete a function execution by its unique ID.", "responses": { "204": { "description": "No content" @@ -11356,12 +11280,12 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 308, + "weight": 385, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11370,9 +11294,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11406,7 +11327,7 @@ "\/functions\/{functionId}\/usage": { "get": { "summary": "Get function usage", - "operationId": "functionsGetFunctionUsage", + "operationId": "functionsGetUsage", "consumes": [ "application\/json" ], @@ -11416,7 +11337,7 @@ "tags": [ "functions" ], - "description": "", + "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", @@ -11426,13 +11347,13 @@ } }, "x-appwrite": { - "method": "getFunctionUsage", - "weight": 293, + "method": "getUsage", + "weight": 386, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/get-function-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -11441,9 +11362,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11509,12 +11427,12 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 310, + "weight": 390, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-variables.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11523,9 +11441,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11570,12 +11485,12 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 309, + "weight": 388, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11584,9 +11499,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11623,6 +11535,12 @@ "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": [ @@ -11658,12 +11576,12 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 311, + "weight": 389, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11672,9 +11590,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11727,12 +11642,12 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 312, + "weight": 391, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/update-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11741,9 +11656,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11788,6 +11700,12 @@ "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": [ @@ -11815,12 +11733,12 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 313, + "weight": 392, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11829,9 +11747,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11886,7 +11801,7 @@ }, "x-appwrite": { "method": "query", - "weight": 331, + "weight": 303, "cookies": false, "type": "graphql", "deprecated": false, @@ -11902,9 +11817,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -11962,7 +11874,7 @@ }, "x-appwrite": { "method": "mutation", - "weight": 330, + "weight": 302, "cookies": false, "type": "graphql", "deprecated": false, @@ -11978,9 +11890,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12038,7 +11947,7 @@ }, "x-appwrite": { "method": "get", - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -12052,9 +11961,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12091,7 +11997,7 @@ }, "x-appwrite": { "method": "getAntivirus", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -12105,9 +12011,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12144,7 +12047,7 @@ }, "x-appwrite": { "method": "getCache", - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -12158,9 +12061,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12211,9 +12111,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12259,7 +12156,7 @@ }, "x-appwrite": { "method": "getDB", - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -12273,9 +12170,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12326,62 +12220,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [], - "Key": [] - } - ] - } - }, - "\/health\/queue": { - "get": { - "summary": "Get queue", - "operationId": "healthGetQueue", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "health" - ], - "description": "Check the Appwrite queue messaging servers are up and connection is successful.", - "responses": { - "200": { - "description": "Health Status", - "schema": { - "$ref": "#\/definitions\/healthStatus" - } - } - }, - "x-appwrite": { - "method": "getQueue", - "weight": 129, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "health\/get-queue.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "health.read", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12432,9 +12270,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12496,9 +12331,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12560,9 +12392,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12633,9 +12462,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12683,7 +12509,7 @@ }, "x-appwrite": { "method": "getFailedJobs", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -12697,9 +12523,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12723,8 +12546,9 @@ "v1-audits", "v1-mails", "v1-functions", - "v1-usage", - "v1-usage-dump", + "v1-stats-resources", + "v1-stats-usage", + "v1-stats-usage-dump", "v1-webhooks", "v1-certificates", "v1-builds", @@ -12785,9 +12609,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12849,9 +12670,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12913,9 +12731,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -12977,9 +12792,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13041,9 +12853,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13067,9 +12876,70 @@ ] } }, - "\/health\/queue\/usage": { + "\/health\/queue\/stats-resources": { "get": { - "summary": "Get usage queue", + "summary": "Get stats resources queue", + "operationId": "healthGetQueueStatsResources", + "consumes": [ + "application\/json" + ], + "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", + "weight": 143, + "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": [ "application\/json" @@ -13091,12 +12961,12 @@ }, "x-appwrite": { "method": "getQueueUsage", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, "demo": "health\/get-queue-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -13105,9 +12975,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13131,10 +12998,10 @@ ] } }, - "\/health\/queue\/usage-dump": { + "\/health\/queue\/stats-usage-dump": { "get": { "summary": "Get usage dump queue", - "operationId": "healthGetQueueUsageDump", + "operationId": "healthGetQueueStatsUsageDump", "consumes": [ "application\/json" ], @@ -13154,13 +13021,13 @@ } }, "x-appwrite": { - "method": "getQueueUsageDump", - "weight": 144, + "method": "getQueueStatsUsageDump", + "weight": 145, "cookies": false, "type": "", "deprecated": false, - "demo": "health\/get-queue-usage-dump.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-usage-dump.md", + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -13169,9 +13036,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13233,9 +13097,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13283,7 +13144,7 @@ }, "x-appwrite": { "method": "getStorage", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -13297,9 +13158,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13336,7 +13194,7 @@ }, "x-appwrite": { "method": "getStorageLocal", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -13350,9 +13208,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13403,9 +13258,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13442,7 +13294,7 @@ }, "x-appwrite": { "method": "get", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -13458,9 +13310,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13498,7 +13347,7 @@ }, "x-appwrite": { "method": "listCodes", - "weight": 118, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -13514,9 +13363,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13554,7 +13400,7 @@ }, "x-appwrite": { "method": "listContinents", - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -13570,9 +13416,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13610,7 +13453,7 @@ }, "x-appwrite": { "method": "listCountries", - "weight": 119, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -13626,9 +13469,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13666,7 +13506,7 @@ }, "x-appwrite": { "method": "listCountriesEU", - "weight": 120, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -13682,9 +13522,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13722,7 +13559,7 @@ }, "x-appwrite": { "method": "listCountriesPhones", - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -13738,9 +13575,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [] } @@ -13778,7 +13612,7 @@ }, "x-appwrite": { "method": "listCurrencies", - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -13794,9 +13628,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13834,7 +13665,7 @@ }, "x-appwrite": { "method": "listLanguages", - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -13850,9 +13681,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [] } @@ -13890,7 +13718,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -13905,9 +13733,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -13967,7 +13792,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -13982,9 +13807,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14116,7 +13938,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -14127,7 +13949,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -14142,9 +13964,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14284,7 +14103,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -14299,9 +14118,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14328,13 +14144,13 @@ "title": { "type": "string", "description": "Title for push notification.", - "default": null, + "default": "", "x-example": "<TITLE>" }, "body": { "type": "string", "description": "Body for push notification.", - "default": null, + "default": "", "x-example": "<BODY>" }, "topics": { @@ -14366,7 +14182,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "default": {}, "x-example": "{}" }, @@ -14390,7 +14206,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "default": "", "x-example": "<SOUND>" }, @@ -14407,10 +14223,10 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "default": "", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "default": -1, + "x-example": null }, "draft": { "type": "boolean", @@ -14423,12 +14239,34 @@ "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", - "title", - "body" + "messageId" ] } } @@ -14448,7 +14286,7 @@ "tags": [ "messaging" ], - "description": "Update a push notification by its unique ID.\n", + "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", @@ -14459,7 +14297,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -14474,9 +14312,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14600,6 +14435,30 @@ "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": [] } } } @@ -14631,7 +14490,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -14646,9 +14505,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14740,7 +14596,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -14751,12 +14607,12 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 362, "cookies": false, "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.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}", @@ -14766,9 +14622,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14869,7 +14722,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -14884,9 +14737,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14914,9 +14764,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -14928,7 +14776,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -14943,9 +14791,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -14992,7 +14837,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -15007,9 +14852,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15068,7 +14910,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -15083,9 +14925,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15144,7 +14983,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -15159,9 +14998,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15221,7 +15057,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -15236,9 +15072,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15338,7 +15171,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -15353,9 +15186,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15453,7 +15283,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -15468,9 +15298,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15546,7 +15373,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -15561,9 +15388,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15637,7 +15461,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -15652,9 +15476,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15766,7 +15587,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -15781,9 +15602,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15893,7 +15711,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -15908,9 +15726,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -15998,7 +15813,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -16013,9 +15828,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16101,7 +15913,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -16116,9 +15928,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16218,7 +16027,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -16233,9 +16042,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16333,7 +16139,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -16348,9 +16154,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16494,7 +16297,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -16509,9 +16312,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16652,7 +16452,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -16667,9 +16467,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16757,7 +16554,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -16772,9 +16569,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16860,7 +16654,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -16875,9 +16669,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -16965,7 +16756,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -16980,9 +16771,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17068,7 +16856,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -17083,9 +16871,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17173,7 +16958,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -17188,9 +16973,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17276,7 +17058,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -17291,9 +17073,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17381,7 +17160,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -17396,9 +17175,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17484,7 +17260,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -17499,9 +17275,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17529,9 +17302,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -17543,7 +17314,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -17558,9 +17329,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17607,7 +17375,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -17622,9 +17390,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17683,7 +17448,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -17698,9 +17463,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17759,7 +17521,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -17774,9 +17536,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17834,7 +17593,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -17849,9 +17608,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17926,7 +17682,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -17941,9 +17697,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -17988,7 +17741,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -18003,9 +17756,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18057,9 +17807,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -18071,7 +17819,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -18086,9 +17834,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18135,7 +17880,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -18150,9 +17895,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18211,7 +17953,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -18226,9 +17968,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18294,7 +18033,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -18311,9 +18050,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18386,7 +18122,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -18401,9 +18137,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18439,9 +18172,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -18453,7 +18184,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -18470,9 +18201,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18517,7 +18245,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18528,7 +18256,7 @@ }, "x-appwrite": { "method": "list", - "weight": 339, + "weight": 311, "cookies": false, "type": "", "deprecated": false, @@ -18542,9 +18270,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18592,7 +18317,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18603,7 +18328,7 @@ }, "x-appwrite": { "method": "createAppwriteMigration", - "weight": 334, + "weight": 306, "cookies": false, "type": "", "deprecated": false, @@ -18617,9 +18342,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18647,19 +18369,19 @@ }, "endpoint": { "type": "string", - "description": "Source's Appwrite Endpoint", + "description": "Source Appwrite endpoint", "default": null, "x-example": "https:\/\/example.com" }, "projectId": { "type": "string", - "description": "Source's Project ID", + "description": "Source Project ID", "default": null, "x-example": "<PROJECT_ID>" }, "apiKey": { "type": "string", - "description": "Source's API Key", + "description": "Source API Key", "default": null, "x-example": "<API_KEY>" } @@ -18688,7 +18410,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18699,7 +18421,7 @@ }, "x-appwrite": { "method": "getAppwriteReport", - "weight": 341, + "weight": 313, "cookies": false, "type": "", "deprecated": false, @@ -18713,9 +18435,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18765,9 +18484,92 @@ ] } }, + "\/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", + "weight": 310, + "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": "Migrate Firebase data (Service Account)", + "summary": "Migrate Firebase data", "operationId": "migrationsCreateFirebaseMigration", "consumes": [ "application\/json" @@ -18778,7 +18580,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -18789,7 +18591,7 @@ }, "x-appwrite": { "method": "createFirebaseMigration", - "weight": 336, + "weight": 307, "cookies": false, "type": "", "deprecated": false, @@ -18803,9 +18605,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -18847,192 +18646,6 @@ ] } }, - "\/migrations\/firebase\/deauthorize": { - "get": { - "summary": "Revoke Appwrite's authorization to access Firebase projects", - "operationId": "migrationsDeleteFirebaseAuth", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "File", - "schema": { - "type": "file" - } - } - }, - "x-appwrite": { - "method": "deleteFirebaseAuth", - "weight": 347, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/delete-firebase-auth.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, - "\/migrations\/firebase\/oauth": { - "post": { - "summary": "Migrate Firebase data (OAuth)", - "operationId": "migrationsCreateFirebaseOAuthMigration", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "202": { - "description": "Migration", - "schema": { - "$ref": "#\/definitions\/migration" - } - } - }, - "x-appwrite": { - "method": "createFirebaseOAuthMigration", - "weight": 335, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/create-firebase-o-auth-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, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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" - } - }, - "projectId": { - "type": "string", - "description": "Project ID of the Firebase Project", - "default": null, - "x-example": "<PROJECT_ID>" - } - }, - "required": [ - "resources", - "projectId" - ] - } - } - ] - } - }, - "\/migrations\/firebase\/projects": { - "get": { - "summary": "List Firebase projects", - "operationId": "migrationsListFirebaseProjects", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migrations Firebase Projects List", - "schema": { - "$ref": "#\/definitions\/firebaseProjectList" - } - } - }, - "x-appwrite": { - "method": "listFirebaseProjects", - "weight": 346, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/list-firebase-projects.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "migrations.read", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [] - } - }, - "security": [ - { - "Project": [] - } - ] - } - }, "\/migrations\/firebase\/report": { "get": { "summary": "Generate a report on Firebase data", @@ -19046,7 +18659,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19057,7 +18670,7 @@ }, "x-appwrite": { "method": "getFirebaseReport", - "weight": 342, + "weight": 314, "cookies": false, "type": "", "deprecated": false, @@ -19071,9 +18684,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19106,79 +18716,6 @@ ] } }, - "\/migrations\/firebase\/report\/oauth": { - "get": { - "summary": "Generate a report on Firebase data using OAuth", - "operationId": "migrationsGetFirebaseReportOAuth", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "migrations" - ], - "description": "", - "responses": { - "200": { - "description": "Migration Report", - "schema": { - "$ref": "#\/definitions\/migrationReport" - } - } - }, - "x-appwrite": { - "method": "getFirebaseReportOAuth", - "weight": 343, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "migrations\/get-firebase-report-o-auth.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, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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": "projectId", - "description": "Project ID", - "required": true, - "type": "string", - "x-example": "<PROJECT_ID>", - "in": "query" - } - ] - } - }, "\/migrations\/nhost": { "post": { "summary": "Migrate NHost data", @@ -19192,7 +18729,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19203,7 +18740,7 @@ }, "x-appwrite": { "method": "createNHostMigration", - "weight": 338, + "weight": 309, "cookies": false, "type": "", "deprecated": false, @@ -19217,9 +18754,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19315,7 +18849,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19326,7 +18860,7 @@ }, "x-appwrite": { "method": "getNHostReport", - "weight": 349, + "weight": 316, "cookies": false, "type": "", "deprecated": false, @@ -19340,9 +18874,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19437,7 +18968,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19448,7 +18979,7 @@ }, "x-appwrite": { "method": "createSupabaseMigration", - "weight": 337, + "weight": 308, "cookies": false, "type": "", "deprecated": false, @@ -19462,9 +18993,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19553,7 +19081,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19564,7 +19092,7 @@ }, "x-appwrite": { "method": "getSupabaseReport", - "weight": 348, + "weight": 315, "cookies": false, "type": "", "deprecated": false, @@ -19578,9 +19106,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19668,7 +19193,7 @@ "tags": [ "migrations" ], - "description": "", + "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", @@ -19679,7 +19204,7 @@ }, "x-appwrite": { "method": "get", - "weight": 340, + "weight": 312, "cookies": false, "type": "", "deprecated": false, @@ -19693,9 +19218,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19728,7 +19250,7 @@ "tags": [ "migrations" ], - "description": "", + "description": "Retry a failed migration. This endpoint allows you to retry a migration that has previously failed.", "responses": { "202": { "description": "Migration", @@ -19739,7 +19261,7 @@ }, "x-appwrite": { "method": "retry", - "weight": 350, + "weight": 317, "cookies": false, "type": "", "deprecated": false, @@ -19753,9 +19275,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19786,7 +19305,7 @@ "tags": [ "migrations" ], - "description": "", + "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" @@ -19794,7 +19313,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 351, + "weight": 318, "cookies": false, "type": "", "deprecated": false, @@ -19808,9 +19327,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19845,7 +19361,7 @@ "tags": [ "project" ], - "description": "", + "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", @@ -19856,12 +19372,12 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 196, + "weight": 197, "cookies": false, "type": "", "deprecated": false, "demo": "project\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -19870,9 +19386,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19942,7 +19455,7 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 198, + "weight": 199, "cookies": false, "type": "", "deprecated": false, @@ -19956,9 +19469,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -19992,7 +19502,7 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 197, + "weight": 198, "cookies": false, "type": "", "deprecated": false, @@ -20006,9 +19516,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20036,6 +19543,12 @@ "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": [ @@ -20071,7 +19584,7 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 199, + "weight": 200, "cookies": false, "type": "", "deprecated": false, @@ -20085,9 +19598,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20131,7 +19641,7 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 200, + "weight": 201, "cookies": false, "type": "", "deprecated": false, @@ -20145,9 +19655,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20183,6 +19690,12 @@ "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": [ @@ -20210,7 +19723,7 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 201, + "weight": 202, "cookies": false, "type": "", "deprecated": false, @@ -20224,9 +19737,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20261,7 +19771,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all projects. You can use the query params to filter your results. ", "responses": { "200": { "description": "Projects List", @@ -20272,12 +19782,12 @@ }, "x-appwrite": { "method": "list", - "weight": 151, + "weight": 152, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/list.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20286,9 +19796,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20334,7 +19841,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new project. You can create a maximum of 100 projects per account. ", "responses": { "201": { "description": "Project", @@ -20345,12 +19852,12 @@ }, "x-appwrite": { "method": "create", - "weight": 150, + "weight": 151, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20359,9 +19866,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20402,8 +19906,7 @@ "default": "default", "x-example": "default", "enum": [ - "default", - "fra" + "default" ], "x-enum-name": null, "x-enum-keys": [] @@ -20486,7 +19989,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20497,12 +20000,12 @@ }, "x-appwrite": { "method": "get", - "weight": 152, + "weight": 153, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20511,9 +20014,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20546,7 +20046,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update a project by its unique ID.", "responses": { "200": { "description": "Project", @@ -20557,12 +20057,12 @@ }, "x-appwrite": { "method": "update", - "weight": 153, + "weight": 154, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20571,9 +20071,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20676,7 +20173,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a project by its unique ID.", "responses": { "204": { "description": "No content" @@ -20684,12 +20181,12 @@ }, "x-appwrite": { "method": "delete", - "weight": 170, + "weight": 171, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20698,9 +20195,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20735,7 +20229,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20746,12 +20240,12 @@ }, "x-appwrite": { "method": "updateApiStatus", - "weight": 157, + "weight": 158, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-api-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20760,9 +20254,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20829,7 +20320,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -20840,12 +20331,12 @@ }, "x-appwrite": { "method": "updateApiStatusAll", - "weight": 158, + "weight": 159, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-api-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20854,9 +20345,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20909,7 +20397,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update how long sessions created within a project should stay active for.", "responses": { "200": { "description": "Project", @@ -20920,12 +20408,12 @@ }, "x-appwrite": { "method": "updateAuthDuration", - "weight": 163, + "weight": 164, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-duration.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -20934,9 +20422,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -20989,7 +20474,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the maximum number of users allowed in this project. Set to 0 for unlimited users. ", "responses": { "200": { "description": "Project", @@ -21000,12 +20485,12 @@ }, "x-appwrite": { "method": "updateAuthLimit", - "weight": 162, + "weight": 163, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21014,9 +20499,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21069,7 +20551,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21080,12 +20562,12 @@ }, "x-appwrite": { "method": "updateAuthSessionsLimit", - "weight": 168, + "weight": 169, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-sessions-limit.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21094,9 +20576,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21138,7 +20617,7 @@ }, "\/projects\/{projectId}\/auth\/memberships-privacy": { "patch": { - "summary": "Update project team sensitive attributes", + "summary": "Update project memberships privacy attributes", "operationId": "projectsUpdateMembershipsPrivacy", "consumes": [ "application\/json" @@ -21149,7 +20628,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21160,12 +20639,12 @@ }, "x-appwrite": { "method": "updateMembershipsPrivacy", - "weight": 161, + "weight": 162, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-memberships-privacy.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21174,9 +20653,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21243,7 +20719,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the list of mock phone numbers for testing. Use these numbers to bypass SMS verification in development. ", "responses": { "200": { "description": "Project", @@ -21254,12 +20730,12 @@ }, "x-appwrite": { "method": "updateMockNumbers", - "weight": 169, + "weight": 170, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-mock-numbers.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21268,9 +20744,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21326,7 +20799,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21337,12 +20810,12 @@ }, "x-appwrite": { "method": "updateAuthPasswordDictionary", - "weight": 166, + "weight": 167, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-password-dictionary.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21351,9 +20824,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21406,7 +20876,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21417,12 +20887,12 @@ }, "x-appwrite": { "method": "updateAuthPasswordHistory", - "weight": 165, + "weight": 166, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-password-history.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21431,9 +20901,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21486,7 +20953,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21497,12 +20964,12 @@ }, "x-appwrite": { "method": "updatePersonalDataCheck", - "weight": 167, + "weight": 168, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-personal-data-check.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21511,9 +20978,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21566,7 +21030,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Enable or disable session email alerts. When enabled, users will receive email notifications when new sessions are created.", "responses": { "200": { "description": "Project", @@ -21577,12 +21041,12 @@ }, "x-appwrite": { "method": "updateSessionAlerts", - "weight": 160, + "weight": 161, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-session-alerts.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21591,9 +21055,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21646,7 +21107,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21657,12 +21118,12 @@ }, "x-appwrite": { "method": "updateAuthStatus", - "weight": 164, + "weight": 165, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-auth-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21671,9 +21132,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21745,7 +21203,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Create a new JWT token. This token can be used to authenticate users with custom scopes and expiration time. ", "responses": { "201": { "description": "JWT", @@ -21756,12 +21214,12 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 182, + "weight": 183, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create-j-w-t.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21770,9 +21228,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21834,7 +21289,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a list of all API keys from the current project. ", "responses": { "200": { "description": "API Keys List", @@ -21845,12 +21300,12 @@ }, "x-appwrite": { "method": "listKeys", - "weight": 178, + "weight": 179, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/list-keys.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21859,9 +21314,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21894,7 +21346,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -21905,12 +21357,12 @@ }, "x-appwrite": { "method": "createKey", - "weight": 177, + "weight": 178, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -21919,9 +21371,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -21990,7 +21439,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22001,12 +21450,12 @@ }, "x-appwrite": { "method": "getKey", - "weight": 179, + "weight": 180, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22015,9 +21464,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22058,7 +21504,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22069,12 +21515,12 @@ }, "x-appwrite": { "method": "updateKey", - "weight": 180, + "weight": 181, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22083,9 +21529,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22158,7 +21601,7 @@ "tags": [ "projects" ], - "description": "", + "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" @@ -22166,12 +21609,12 @@ }, "x-appwrite": { "method": "deleteKey", - "weight": 181, + "weight": 182, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete-key.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22180,9 +21623,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22225,7 +21665,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22236,12 +21676,12 @@ }, "x-appwrite": { "method": "updateOAuth2", - "weight": 159, + "weight": 160, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-o-auth2.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22250,9 +21690,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22366,7 +21803,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22377,12 +21814,12 @@ }, "x-appwrite": { "method": "listPlatforms", - "weight": 184, + "weight": 185, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/list-platforms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22391,9 +21828,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22426,7 +21860,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22437,12 +21871,12 @@ }, "x-appwrite": { "method": "createPlatform", - "weight": 183, + "weight": 184, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22451,9 +21885,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22550,7 +21981,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22561,12 +21992,12 @@ }, "x-appwrite": { "method": "getPlatform", - "weight": 185, + "weight": 186, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22575,9 +22006,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22618,7 +22046,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22629,12 +22057,12 @@ }, "x-appwrite": { "method": "updatePlatform", - "weight": 186, + "weight": 187, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22643,9 +22071,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22720,7 +22145,7 @@ "tags": [ "projects" ], - "description": "", + "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" @@ -22728,12 +22153,12 @@ }, "x-appwrite": { "method": "deletePlatform", - "weight": 187, + "weight": 188, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete-platform.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22742,9 +22167,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22787,7 +22209,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of a specific service. Use this endpoint to enable or disable a service in your project. ", "responses": { "200": { "description": "Project", @@ -22798,12 +22220,12 @@ }, "x-appwrite": { "method": "updateServiceStatus", - "weight": 155, + "weight": 156, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-service-status.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22812,9 +22234,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22853,6 +22272,7 @@ "storage", "teams", "users", + "sites", "functions", "graphql", "messaging" @@ -22889,7 +22309,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the status of all services. Use this endpoint to enable or disable all optional services at once. ", "responses": { "200": { "description": "Project", @@ -22900,12 +22320,12 @@ }, "x-appwrite": { "method": "updateServiceStatusAll", - "weight": 156, + "weight": 157, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-service-status-all.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22914,9 +22334,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -22969,7 +22386,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -22980,12 +22397,12 @@ }, "x-appwrite": { "method": "updateSmtp", - "weight": 188, + "weight": 189, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-smtp.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -22994,9 +22411,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23097,11 +22511,13 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "projects" ], - "description": "", + "description": "Send a test email to verify SMTP configuration. ", "responses": { "204": { "description": "No content" @@ -23109,12 +22525,12 @@ }, "x-appwrite": { "method": "createSmtpTest", - "weight": 189, + "weight": 190, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create-smtp-test.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23123,9 +22539,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23238,7 +22651,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Update the team ID of a project allowing for it to be transferred to another team.", "responses": { "200": { "description": "Project", @@ -23249,12 +22662,12 @@ }, "x-appwrite": { "method": "updateTeam", - "weight": 154, + "weight": 155, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-team.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23263,9 +22676,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23318,7 +22728,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -23329,12 +22739,12 @@ }, "x-appwrite": { "method": "getEmailTemplate", - "weight": 191, + "weight": 192, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23343,9 +22753,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23540,23 +22947,23 @@ "tags": [ "projects" ], - "description": "", + "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": "Project", + "description": "EmailTemplate", "schema": { - "$ref": "#\/definitions\/project" + "$ref": "#\/definitions\/emailTemplate" } } }, "x-appwrite": { "method": "updateEmailTemplate", - "weight": 193, + "weight": 194, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23565,9 +22972,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -23805,7 +23209,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -23816,12 +23220,12 @@ }, "x-appwrite": { "method": "deleteEmailTemplate", - "weight": 195, + "weight": 196, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete-email-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -23830,9 +23234,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24029,7 +23430,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a custom SMS template for the specified locale and type returning it's contents.", "responses": { "200": { "description": "SmsTemplate", @@ -24040,12 +23441,12 @@ }, "x-appwrite": { "method": "getSmsTemplate", - "weight": 190, + "weight": 191, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24054,9 +23455,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24248,7 +23646,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24259,12 +23657,12 @@ }, "x-appwrite": { "method": "updateSmsTemplate", - "weight": 192, + "weight": 193, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24273,9 +23671,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24485,7 +23880,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24496,12 +23891,12 @@ }, "x-appwrite": { "method": "deleteSmsTemplate", - "weight": 194, + "weight": 195, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete-sms-template.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24510,9 +23905,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24706,7 +24098,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24717,12 +24109,12 @@ }, "x-appwrite": { "method": "listWebhooks", - "weight": 172, + "weight": 173, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/list-webhooks.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24731,9 +24123,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24766,7 +24155,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24777,12 +24166,12 @@ }, "x-appwrite": { "method": "createWebhook", - "weight": 171, + "weight": 172, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/create-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24791,9 +24180,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24888,7 +24274,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Get a webhook by its unique ID. This endpoint returns details about a specific webhook configured for a project. ", "responses": { "200": { "description": "Webhook", @@ -24899,12 +24285,12 @@ }, "x-appwrite": { "method": "getWebhook", - "weight": 173, + "weight": 174, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/get-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24913,9 +24299,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -24956,7 +24339,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -24967,12 +24350,12 @@ }, "x-appwrite": { "method": "updateWebhook", - "weight": 174, + "weight": 175, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -24981,9 +24364,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25082,7 +24462,7 @@ "tags": [ "projects" ], - "description": "", + "description": "Delete a webhook by its unique ID. Once deleted, the webhook will no longer receive project events. ", "responses": { "204": { "description": "No content" @@ -25090,12 +24470,12 @@ }, "x-appwrite": { "method": "deleteWebhook", - "weight": 176, + "weight": 177, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/delete-webhook.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -25104,9 +24484,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25149,7 +24526,7 @@ "tags": [ "projects" ], - "description": "", + "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", @@ -25160,12 +24537,12 @@ }, "x-appwrite": { "method": "updateWebhookSignature", - "weight": 175, + "weight": 176, "cookies": false, "type": "", "deprecated": false, "demo": "projects\/update-webhook-signature.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -25174,9 +24551,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25230,7 +24604,7 @@ }, "x-appwrite": { "method": "listRules", - "weight": 317, + "weight": 289, "cookies": false, "type": "", "deprecated": false, @@ -25244,9 +24618,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25259,7 +24630,7 @@ "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, resourceType, resourceId, url", + "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", @@ -25279,10 +24650,12 @@ "in": "query" } ] - }, + } + }, + "\/proxy\/rules\/api": { "post": { - "summary": "Create rule", - "operationId": "proxyCreateRule", + "summary": "Create API rule", + "operationId": "proxyCreateAPIRule", "consumes": [ "application\/json" ], @@ -25292,7 +24665,7 @@ "tags": [ "proxy" ], - "description": "Create a new proxy rule.", + "description": "Create a new proxy rule for serving Appwrite's API on custom domain.", "responses": { "201": { "description": "Rule", @@ -25302,24 +24675,90 @@ } }, "x-appwrite": { - "method": "createRule", - "weight": 316, + "method": "createAPIRule", + "weight": 425, "cookies": false, "type": "", "deprecated": false, - "demo": "proxy\/create-rule.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/create-rule.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", + "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", + "weight": 427, + "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, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25342,28 +24781,200 @@ "default": null, "x-example": null }, - "resourceType": { + "functionId": { "type": "string", - "description": "Action definition for the rule. Possible values are \"api\", \"function\"", + "description": "ID of function to be executed.", "default": null, - "x-example": "api", - "enum": [ - "api", - "function" - ], - "x-enum-name": null, - "x-enum-keys": [] + "x-example": "<FUNCTION_ID>" }, - "resourceId": { + "branch": { "type": "string", - "description": "ID of resource for the action type. If resourceType is \"api\", leave empty. If resourceType is \"function\", provide ID of the function.", + "description": "Name of VCS branch to deploy changes automatically", "default": "", - "x-example": "<RESOURCE_ID>" + "x-example": "<BRANCH>" } }, "required": [ "domain", - "resourceType" + "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", + "weight": 428, + "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" + ] + } + }, + "required": [ + "domain", + "url", + "statusCode" + ] + } + } + ] + } + }, + "\/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", + "weight": 426, + "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" ] } } @@ -25394,7 +25005,7 @@ }, "x-appwrite": { "method": "getRule", - "weight": 318, + "weight": 290, "cookies": false, "type": "", "deprecated": false, @@ -25408,9 +25019,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25449,7 +25057,7 @@ }, "x-appwrite": { "method": "deleteRule", - "weight": 319, + "weight": 291, "cookies": false, "type": "", "deprecated": false, @@ -25463,9 +25071,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25500,7 +25105,7 @@ "tags": [ "proxy" ], - "description": "", + "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", @@ -25511,12 +25116,12 @@ }, "x-appwrite": { "method": "updateRuleVerification", - "weight": 320, + "weight": 292, "cookies": false, "type": "", "deprecated": false, "demo": "proxy\/update-rule-verification.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -25525,9 +25130,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25549,6 +25151,2519 @@ ] } }, + "\/sites": { + "get": { + "summary": "List sites", + "operationId": "sitesList", + "consumes": [ + "application\/json" + ], + "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", + "weight": 397, + "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", + "weight": 395, + "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", + "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", + "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" + ], + "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": [ + "application\/json" + ], + "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", + "weight": 400, + "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": [ + "application\/json" + ], + "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", + "weight": 423, + "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": [ + "application\/json" + ], + "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", + "weight": 419, + "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": [ + "application\/json" + ], + "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", + "weight": 420, + "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": [ + "application\/json" + ], + "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", + "weight": 421, + "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": [ + "application\/json" + ], + "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", + "weight": 396, + "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", + "weight": 398, + "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", + "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", + "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" + ], + "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", + "weight": 399, + "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", + "weight": 406, + "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": [ + "application\/json" + ], + "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", + "weight": 405, + "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", + "weight": 401, + "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", + "weight": 409, + "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", + "weight": 402, + "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", + "weight": 403, + "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": [ + "application\/json" + ], + "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", + "weight": 404, + "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", + "weight": 407, + "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": "Download deployment", + "operationId": "sitesGetDeploymentDownload", + "consumes": [ + "application\/json" + ], + "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", + "weight": 408, + "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", + "weight": 410, + "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": [ + "application\/json" + ], + "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", + "weight": 412, + "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": [ + "application\/json" + ], + "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", + "weight": 411, + "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", + "weight": 413, + "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": [ + "application\/json" + ], + "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", + "weight": 422, + "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": [ + "application\/json" + ], + "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", + "weight": 416, + "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", + "weight": 414, + "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": [ + "application\/json" + ], + "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", + "weight": 415, + "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", + "weight": 417, + "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", + "weight": 418, + "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", @@ -25573,7 +27688,7 @@ }, "x-appwrite": { "method": "listBuckets", - "weight": 203, + "weight": 204, "cookies": false, "type": "", "deprecated": false, @@ -25587,9 +27702,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25647,7 +27759,7 @@ }, "x-appwrite": { "method": "createBucket", - "weight": 202, + "weight": 203, "cookies": false, "type": "", "deprecated": false, @@ -25661,9 +27773,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25788,7 +27897,7 @@ }, "x-appwrite": { "method": "getBucket", - "weight": 204, + "weight": 205, "cookies": false, "type": "", "deprecated": false, @@ -25802,9 +27911,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25849,7 +27955,7 @@ }, "x-appwrite": { "method": "updateBucket", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -25863,9 +27969,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -25984,7 +28087,7 @@ }, "x-appwrite": { "method": "deleteBucket", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -25998,9 +28101,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26047,7 +28147,7 @@ }, "x-appwrite": { "method": "listFiles", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -26063,9 +28163,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26132,7 +28229,7 @@ }, "x-appwrite": { "method": "createFile", - "weight": 207, + "weight": 208, "cookies": false, "type": "upload", "deprecated": false, @@ -26148,9 +28245,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26226,7 +28320,7 @@ }, "x-appwrite": { "method": "getFile", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -26242,9 +28336,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26298,7 +28389,7 @@ }, "x-appwrite": { "method": "updateFile", - "weight": 214, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -26314,9 +28405,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26389,7 +28477,7 @@ }, "x-appwrite": { "method": "deleteFile", - "weight": 215, + "weight": 216, "cookies": false, "type": "", "deprecated": false, @@ -26405,9 +28493,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26463,7 +28548,7 @@ }, "x-appwrite": { "method": "getFileDownload", - "weight": 211, + "weight": 212, "cookies": false, "type": "location", "deprecated": false, @@ -26479,9 +28564,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26537,7 +28619,7 @@ }, "x-appwrite": { "method": "getFilePreview", - "weight": 210, + "weight": 211, "cookies": false, "type": "location", "deprecated": false, @@ -26553,9 +28635,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26704,6 +28783,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -26738,7 +28818,7 @@ }, "x-appwrite": { "method": "getFileView", - "weight": 212, + "weight": 213, "cookies": false, "type": "location", "deprecated": false, @@ -26754,9 +28834,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26801,7 +28878,7 @@ "tags": [ "storage" ], - "description": "", + "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", @@ -26812,12 +28889,12 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 216, + "weight": 217, "cookies": false, "type": "", "deprecated": false, "demo": "storage\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -26826,9 +28903,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26875,7 +28949,7 @@ "tags": [ "storage" ], - "description": "", + "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", @@ -26886,12 +28960,12 @@ }, "x-appwrite": { "method": "getBucketUsage", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, "demo": "storage\/get-bucket-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -26900,9 +28974,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -26968,7 +29039,7 @@ }, "x-appwrite": { "method": "list", - "weight": 219, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -26984,9 +29055,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27045,7 +29113,7 @@ }, "x-appwrite": { "method": "create", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -27061,9 +29129,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27139,7 +29204,7 @@ }, "x-appwrite": { "method": "get", - "weight": 220, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -27155,9 +29220,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27203,7 +29265,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -27219,9 +29281,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27280,7 +29339,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -27296,9 +29355,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27346,7 +29402,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -27360,9 +29416,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27420,7 +29473,7 @@ }, "x-appwrite": { "method": "listMemberships", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -27436,9 +29489,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27461,7 +29511,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: userId, teamId, invited, joined, confirm", + "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", @@ -27505,7 +29555,7 @@ }, "x-appwrite": { "method": "createMembership", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -27521,9 +29571,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27622,7 +29669,7 @@ }, "x-appwrite": { "method": "getMembership", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -27638,9 +29685,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27694,7 +29738,7 @@ }, "x-appwrite": { "method": "updateMembership", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -27710,9 +29754,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27782,7 +29823,7 @@ }, "x-appwrite": { "method": "deleteMembership", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -27798,9 +29839,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27856,7 +29894,7 @@ }, "x-appwrite": { "method": "updateMembershipStatus", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -27871,9 +29909,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -27953,7 +29988,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -27968,9 +30003,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28015,7 +30047,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -28030,9 +30062,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28097,7 +30126,7 @@ }, "x-appwrite": { "method": "list", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -28111,9 +30140,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28171,7 +30197,7 @@ }, "x-appwrite": { "method": "create", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -28185,9 +30211,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28268,7 +30291,7 @@ }, "x-appwrite": { "method": "createArgon2User", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -28282,9 +30305,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28361,7 +30381,7 @@ }, "x-appwrite": { "method": "createBcryptUser", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -28375,9 +30395,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28454,7 +30471,7 @@ }, "x-appwrite": { "method": "listIdentities", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -28468,9 +30485,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28525,7 +30539,7 @@ }, "x-appwrite": { "method": "deleteIdentity", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -28539,9 +30553,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28588,7 +30599,7 @@ }, "x-appwrite": { "method": "createMD5User", - "weight": 234, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -28602,9 +30613,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28681,7 +30689,7 @@ }, "x-appwrite": { "method": "createPHPassUser", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -28695,9 +30703,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28774,7 +30779,7 @@ }, "x-appwrite": { "method": "createScryptUser", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -28788,9 +30793,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -28902,7 +30904,7 @@ }, "x-appwrite": { "method": "createScryptModifiedUser", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -28916,9 +30918,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29016,7 +31015,7 @@ }, "x-appwrite": { "method": "createSHAUser", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -29030,9 +31029,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29119,7 +31115,7 @@ "tags": [ "users" ], - "description": "", + "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", @@ -29130,12 +31126,12 @@ }, "x-appwrite": { "method": "getUsage", - "weight": 274, + "weight": 275, "cookies": false, "type": "", "deprecated": false, "demo": "users\/get-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -29144,9 +31140,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29204,7 +31197,7 @@ }, "x-appwrite": { "method": "get", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -29218,9 +31211,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29260,7 +31250,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -29274,9 +31264,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29323,7 +31310,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -29337,9 +31324,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29404,7 +31388,7 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -29418,9 +31402,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29488,7 +31469,7 @@ }, "x-appwrite": { "method": "updateLabels", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -29502,9 +31483,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29572,7 +31550,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -29586,9 +31564,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29647,7 +31622,7 @@ }, "x-appwrite": { "method": "listMemberships", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -29661,9 +31636,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29682,6 +31654,27 @@ "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" } ] } @@ -29710,7 +31703,7 @@ }, "x-appwrite": { "method": "updateMfa", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -29724,9 +31717,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29774,24 +31764,19 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "schema": { - "$ref": "#\/definitions\/user" - } + "204": { + "description": "No content" } }, "x-appwrite": { "method": "deleteMfaAuthenticator", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -29805,9 +31790,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29867,7 +31849,7 @@ }, "x-appwrite": { "method": "listMfaFactors", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -29881,9 +31863,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29930,7 +31909,7 @@ }, "x-appwrite": { "method": "getMfaRecoveryCodes", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -29944,9 +31923,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -29991,7 +31967,7 @@ }, "x-appwrite": { "method": "updateMfaRecoveryCodes", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -30005,9 +31981,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30052,7 +32025,7 @@ }, "x-appwrite": { "method": "createMfaRecoveryCodes", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -30066,9 +32039,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30115,7 +32085,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -30129,9 +32099,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30196,7 +32163,7 @@ }, "x-appwrite": { "method": "updatePassword", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -30210,9 +32177,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30277,7 +32241,7 @@ }, "x-appwrite": { "method": "updatePhone", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -30291,9 +32255,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30358,7 +32319,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -30372,9 +32333,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30419,7 +32377,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -30433,9 +32391,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30500,7 +32455,7 @@ }, "x-appwrite": { "method": "listSessions", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -30514,9 +32469,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30561,7 +32513,7 @@ }, "x-appwrite": { "method": "createSession", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -30575,9 +32527,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30617,7 +32566,7 @@ }, "x-appwrite": { "method": "deleteSessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -30631,9 +32580,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30675,7 +32621,7 @@ }, "x-appwrite": { "method": "deleteSession", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -30689,9 +32635,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30746,7 +32689,7 @@ }, "x-appwrite": { "method": "updateStatus", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -30760,9 +32703,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30827,7 +32767,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -30842,9 +32782,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -30901,7 +32838,7 @@ }, "x-appwrite": { "method": "createTarget", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -30916,9 +32853,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31016,7 +32950,7 @@ }, "x-appwrite": { "method": "getTarget", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -31031,9 +32965,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31086,7 +33017,7 @@ }, "x-appwrite": { "method": "updateTarget", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -31101,9 +33032,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31166,9 +33094,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], @@ -31180,7 +33106,7 @@ }, "x-appwrite": { "method": "deleteTarget", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -31195,9 +33121,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31252,7 +33175,7 @@ }, "x-appwrite": { "method": "createToken", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -31266,9 +33189,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31336,7 +33256,7 @@ }, "x-appwrite": { "method": "updateEmailVerification", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -31350,9 +33270,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31417,7 +33334,7 @@ }, "x-appwrite": { "method": "updatePhoneVerification", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -31431,9 +33348,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31474,10 +33388,10 @@ ] } }, - "\/vcs\/github\/installations\/{installationId}\/providerRepositories": { - "get": { - "summary": "List repositories", - "operationId": "vcsListRepositories", + "\/vcs\/github\/installations\/{installationId}\/detections": { + "post": { + "summary": "Create repository detection", + "operationId": "vcsCreateRepositoryDetection", "consumes": [ "application\/json" ], @@ -31487,34 +33401,31 @@ "tags": [ "vcs" ], - "description": "", + "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": "Provider Repositories List", + "description": "DetectionFramework", "schema": { - "$ref": "#\/definitions\/providerRepositoryList" + "$ref": "#\/definitions\/detectionFramework" } } }, "x-appwrite": { - "method": "listRepositories", + "method": "createRepositoryDetection", "weight": 279, "cookies": false, "type": "", "deprecated": false, - "demo": "vcs\/list-repositories.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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.read", + "scope": "vcs.write", "platforms": [ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31533,6 +33444,116 @@ "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": [ + "application\/json" + ], + "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", + "weight": 280, + "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.", @@ -31556,7 +33577,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31567,12 +33588,12 @@ }, "x-appwrite": { "method": "createRepository", - "weight": 280, + "weight": 281, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/create-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31581,9 +33602,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31643,7 +33661,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31654,12 +33672,12 @@ }, "x-appwrite": { "method": "getRepository", - "weight": 281, + "weight": 282, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/get-repository.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31668,9 +33686,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31713,7 +33728,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31724,12 +33739,12 @@ }, "x-appwrite": { "method": "listRepositoryBranches", - "weight": 282, + "weight": 283, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/list-repository-branches.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31738,9 +33753,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31783,7 +33795,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -31794,12 +33806,12 @@ }, "x-appwrite": { "method": "getRepositoryContents", - "weight": 277, + "weight": 278, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/get-repository-contents.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31808,9 +33820,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -31849,10 +33858,10 @@ ] } }, - "\/vcs\/github\/installations\/{installationId}\/providerRepositories\/{providerRepositoryId}\/detection": { - "post": { - "summary": "Detect runtime settings from source code", - "operationId": "vcsCreateRepositoryDetection", + "\/vcs\/github\/installations\/{installationId}\/repositories\/{repositoryId}": { + "patch": { + "summary": "Authorize external deployment", + "operationId": "vcsUpdateExternalDeployments", "consumes": [ "application\/json" ], @@ -31862,90 +33871,7 @@ "tags": [ "vcs" ], - "description": "", - "responses": { - "200": { - "description": "Detection", - "schema": { - "$ref": "#\/definitions\/detection" - } - } - }, - "x-appwrite": { - "method": "createRepositoryDetection", - "weight": 278, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "vcs\/create-repository-detection.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "vcs.write", - "platforms": [ - "console" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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": "payload", - "in": "body", - "schema": { - "type": "object", - "properties": { - "providerRootDirectory": { - "type": "string", - "description": "Path to Root Directory", - "default": "", - "x-example": "<PROVIDER_ROOT_DIRECTORY>" - } - } - } - } - ] - } - }, - "\/vcs\/github\/installations\/{installationId}\/repositories\/{repositoryId}": { - "patch": { - "summary": "Authorize external deployment", - "operationId": "vcsUpdateExternalDeployments", - "consumes": [ - "application\/json" - ], - "produces": [], - "tags": [ - "vcs" - ], - "description": "", + "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" @@ -31953,12 +33879,12 @@ }, "x-appwrite": { "method": "updateExternalDeployments", - "weight": 287, + "weight": 288, "cookies": false, "type": "", "deprecated": false, "demo": "vcs\/update-external-deployments.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", + "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}", @@ -31967,9 +33893,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -32030,7 +33953,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -32041,7 +33964,7 @@ }, "x-appwrite": { "method": "listInstallations", - "weight": 284, + "weight": 285, "cookies": false, "type": "", "deprecated": false, @@ -32055,9 +33978,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -32105,7 +34025,7 @@ "tags": [ "vcs" ], - "description": "", + "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", @@ -32116,7 +34036,7 @@ }, "x-appwrite": { "method": "getInstallation", - "weight": 285, + "weight": 286, "cookies": false, "type": "", "deprecated": false, @@ -32130,9 +34050,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -32163,7 +34080,7 @@ "tags": [ "vcs" ], - "description": "", + "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" @@ -32171,7 +34088,7 @@ }, "x-appwrite": { "method": "deleteInstallation", - "weight": 286, + "weight": 287, "cookies": false, "type": "", "deprecated": false, @@ -32185,9 +34102,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -32263,6 +34177,11 @@ "description": "The Users service allows you to manage your project users.", "x-globalAttributes": [] }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, { "name": "functions", "description": "The Functions Service allows you view, create and manage your Cloud Functions.", @@ -32600,6 +34519,56 @@ "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", @@ -32675,29 +34644,54 @@ "installations" ] }, - "providerRepositoryList": { - "description": "Provider Repositories List", + "providerRepositoryFrameworkList": { + "description": "Framework Provider Repositories List", "type": "object", "properties": { "total": { "type": "integer", - "description": "Total number of providerRepositories documents that matched your query.", + "description": "Total number of frameworkProviderRepositories documents that matched your query.", "x-example": 5, "format": "int32" }, - "providerRepositories": { + "frameworkProviderRepositories": { "type": "array", - "description": "List of providerRepositories.", + "description": "List of frameworkProviderRepositories.", "items": { "type": "object", - "$ref": "#\/definitions\/providerRepository" + "$ref": "#\/definitions\/providerRepositoryFramework" }, "x-example": "" } }, "required": [ "total", - "providerRepositories" + "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": { @@ -32725,6 +34719,31 @@ "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", @@ -33250,31 +35269,6 @@ "migrations" ] }, - "firebaseProjectList": { - "description": "Migrations Firebase 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\/firebaseProject" - }, - "x-example": "" - } - }, - "required": [ - "total", - "projects" - ] - }, "specificationList": { "description": "Specifications List", "type": "object", @@ -35534,6 +37528,352 @@ "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", @@ -35578,19 +37918,39 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "x-example": false }, "runtime": { "type": "string", - "description": "Function execution runtime.", + "description": "Function execution and build runtime.", "x-example": "python-3.8" }, - "deployment": { + "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.", @@ -35618,7 +37978,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { @@ -35683,7 +38043,11 @@ "live", "logging", "runtime", - "deployment", + "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "scopes", "vars", "events", @@ -35882,6 +38246,11 @@ "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.", @@ -35902,6 +38271,7 @@ "name", "description", "value", + "secret", "placeholder", "required", "type" @@ -35980,11 +38350,6 @@ "description": "Is VCS (Version Control System) repository private?", "x-example": true }, - "runtime": { - "type": "string", - "description": "Auto-detected runtime suggestion. Empty if getting response of getRuntime().", - "x-example": "node" - }, "pushedAt": { "type": "string", "description": "Last commit date in ISO 8601 format.", @@ -35997,22 +38362,165 @@ "organization", "provider", "private", - "runtime", "pushedAt" ] }, - "detection": { - "description": "Detection", + "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" + "runtime", + "entrypoint", + "commands" ] }, "vcsContent": { @@ -36115,6 +38623,100 @@ "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", @@ -36154,7 +38756,7 @@ "description": "The entrypoint file to use to execute the deployment code.", "x-example": "index.js" }, - "size": { + "sourceSize": { "type": "integer", "description": "The code size in bytes.", "x-example": 128, @@ -36166,6 +38768,12 @@ "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.", @@ -36176,9 +38784,19 @@ "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 \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".", + "description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", "x-example": "ready" }, "buildLogs": { @@ -36186,7 +38804,7 @@ "description": "The build logs.", "x-example": "Compiling source files..." }, - "buildTime": { + "buildDuration": { "type": "integer", "description": "The current build time in seconds.", "x-example": 128, @@ -36251,13 +38869,16 @@ "resourceId", "resourceType", "entrypoint", - "size", + "sourceSize", "buildSize", + "totalSize", "buildId", "activate", + "screenshotLight", + "screenshotDark", "status", "buildLogs", - "buildTime", + "buildDuration", "providerRepositoryName", "providerRepositoryOwner", "providerRepositoryUrl", @@ -36373,7 +38994,7 @@ }, "duration": { "type": "number", - "description": "Function execution duration in seconds.", + "description": "Resource(function\/site) execution duration in seconds.", "x-example": 0.4, "format": "double" }, @@ -36403,70 +39024,6 @@ "duration" ] }, - "build": { - "description": "Build", - "type": "object", - "properties": { - "$id": { - "type": "string", - "description": "Build ID.", - "x-example": "5e5ea5c16897e" - }, - "deploymentId": { - "type": "string", - "description": "The deployment that created this build.", - "x-example": "5e5ea5c16897e" - }, - "status": { - "type": "string", - "description": "The build status. There are a few different types and each one means something different. \\nFailed - The deployment build has failed. More details can usually be found in buildStderr\\nReady - The deployment build was successful and the deployment is ready to be deployed\\nProcessing - The deployment is currently waiting to have a build triggered\\nBuilding - The deployment is currently being built", - "x-example": "ready" - }, - "stdout": { - "type": "string", - "description": "The stdout of the build.", - "x-example": "" - }, - "stderr": { - "type": "string", - "description": "The stderr of the build.", - "x-example": "" - }, - "startTime": { - "type": "string", - "description": "The deployment creation date in ISO 8601 format.", - "x-example": "2020-10-15T06:38:00.000+00:00" - }, - "endTime": { - "type": "string", - "description": "The time the build was finished in ISO 8601 format.", - "x-example": "2020-10-15T06:38:00.000+00:00" - }, - "duration": { - "type": "integer", - "description": "The build duration in seconds.", - "x-example": 0, - "format": "int32" - }, - "size": { - "type": "integer", - "description": "The code size in bytes.", - "x-example": 128, - "format": "int32" - } - }, - "required": [ - "$id", - "deploymentId", - "status", - "stdout", - "stderr", - "startTime", - "endTime", - "duration", - "size" - ] - }, "project": { "description": "Project", "type": "object", @@ -36591,17 +39148,17 @@ "description": "Whether or not to send session alert emails to users.", "x-example": true }, - "membershipsUserName": { + "authMembershipsUserName": { "type": "boolean", "description": "Whether or not to show user names in the teams membership response.", "x-example": true }, - "membershipsUserEmail": { + "authMembershipsUserEmail": { "type": "boolean", "description": "Whether or not to show user emails in the teams membership response.", "x-example": true }, - "membershipsMfa": { + "authMembershipsMfa": { "type": "boolean", "description": "Whether or not to show user MFA status in the teams membership response.", "x-example": true @@ -36776,6 +39333,11 @@ "description": "Users service status", "x-example": true }, + "serviceStatusForSites": { + "type": "boolean", + "description": "Sites service status", + "x-example": true + }, "serviceStatusForFunctions": { "type": "boolean", "description": "Functions service status", @@ -36815,9 +39377,9 @@ "authPersonalDataCheck", "authMockNumbers", "authSessionAlerts", - "membershipsUserName", - "membershipsUserEmail", - "membershipsMfa", + "authMembershipsUserName", + "authMembershipsUserEmail", + "authMembershipsMfa", "oAuthProviders", "platforms", "webhooks", @@ -36848,6 +39410,7 @@ "serviceStatusForStorage", "serviceStatusForTeams", "serviceStatusForUsers", + "serviceStatusForSites", "serviceStatusForFunctions", "serviceStatusForGraphql", "serviceStatusForMessaging" @@ -37166,6 +39729,11 @@ "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\"", @@ -37183,6 +39751,7 @@ "$updatedAt", "key", "value", + "secret", "resourceType", "resourceId" ] @@ -37494,7 +40063,8 @@ "resourceId": { "type": "string", "description": "Resource ID.", - "x-example": "5e5ea5c16897e" + "x-example": "5e5ea5c16897e", + "x-nullable": true }, "name": { "type": "string", @@ -37506,10 +40076,16 @@ "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": [ - "resourceId", "name", "value" ] @@ -37547,6 +40123,18 @@ "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.", @@ -37582,6 +40170,24 @@ "$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": [ @@ -37590,10 +40196,14 @@ "collectionsTotal", "documentsTotal", "storageTotal", + "databasesReadsTotal", + "databasesWritesTotal", "databases", "collections", "documents", - "storage" + "storage", + "databasesReads", + "databasesWrites" ] }, "usageDatabase": { @@ -37623,6 +40233,18 @@ "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.", @@ -37649,6 +40271,24 @@ "$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": [ @@ -37656,9 +40296,13 @@ "collectionsTotal", "documentsTotal", "storageTotal", + "databaseReadsTotal", + "databaseWritesTotal", "collections", "documents", - "storage" + "storage", + "databaseReads", + "databaseWrites" ] }, "usageCollection": { @@ -37843,6 +40487,21 @@ "$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": [ @@ -37850,7 +40509,9 @@ "filesTotal", "filesStorageTotal", "files", - "storage" + "storage", + "imageTransformations", + "imageTransformationsTotal" ] }, "usageFunctions": { @@ -37949,6 +40610,18 @@ }, "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.", @@ -38011,6 +40684,24 @@ "$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": [ @@ -38028,13 +40719,17 @@ "functions", "deployments", "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", "builds", "buildsStorage", "buildsTime", "buildsMbSeconds", "executions", "executionsTime", - "executionsMbSeconds" + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed" ] }, "usageFunction": { @@ -38064,6 +40759,18 @@ "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.", @@ -38076,6 +40783,12 @@ "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.", @@ -38180,6 +40893,286 @@ "$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": [ @@ -38195,13 +41188,284 @@ "executionsMbSecondsTotal", "deployments", "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", "builds", "buildsStorage", "buildsTime", "buildsMbSeconds", "executions", "executionsTime", - "executionsMbSeconds" + "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": { @@ -38280,6 +41544,18 @@ "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.", @@ -38369,6 +41645,60 @@ "$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": [ @@ -38384,6 +41714,8 @@ "bucketsTotal", "executionsMbSecondsTotal", "buildsMbSecondsTotal", + "databasesReadsTotal", + "databasesWritesTotal", "requests", "network", "users", @@ -38393,7 +41725,14 @@ "databasesStorageBreakdown", "executionsMbSecondsBreakdown", "buildsMbSecondsBreakdown", - "functionsStorageBreakdown" + "functionsStorageBreakdown", + "authPhoneTotal", + "authPhoneEstimate", + "authPhoneCountryBreakdown", + "databasesReads", + "databasesWrites", + "imageTransformations", + "imageTransformationsTotal" ] }, "headers": { @@ -38474,15 +41813,46 @@ "description": "Domain name.", "x-example": "appwrite.company.com" }, - "resourceType": { + "type": { "type": "string", - "description": "Action definition for the rule. Possible values are \"api\", \"function\", or \"redirect\"", + "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" }, - "resourceId": { + "deploymentResourceId": { "type": "string", - "description": "ID of resource for the action type. If resourceType is \"api\" or \"url\", it is empty. If resourceType is \"function\", it is ID of the function.", - "x-example": "myAwesomeFunction" + "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", @@ -38505,8 +41875,14 @@ "$createdAt", "$updatedAt", "domain", - "resourceType", - "resourceId", + "type", + "trigger", + "redirectUrl", + "redirectStatusCode", + "deploymentId", + "deploymentResourceType", + "deploymentResourceId", + "deploymentVcsProviderBranch", "status", "logs", "renewAt" @@ -38592,18 +41968,28 @@ "description": "Console Variables", "type": "object", "properties": { - "_APP_DOMAIN_TARGET": { + "_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_FUNCTIONS_SIZE_LIMIT": { + "_APP_COMPUTE_SIZE_LIMIT": { "type": "integer", "description": "Maximum file size allowed for deployment in bytes.", "x-example": "30000000", @@ -38628,16 +42014,42 @@ "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", + "_APP_DOMAIN_TARGET_CNAME", + "_APP_DOMAIN_TARGET_A", + "_APP_DOMAIN_TARGET_AAAA", "_APP_STORAGE_LIMIT", - "_APP_FUNCTIONS_SIZE_LIMIT", + "_APP_COMPUTE_SIZE_LIMIT", "_APP_USAGE_STATS", "_APP_VCS_ENABLED", "_APP_DOMAIN_ENABLED", - "_APP_ASSISTANT_ENABLED" + "_APP_ASSISTANT_ENABLED", + "_APP_DOMAIN_SITES", + "_APP_DOMAIN_FUNCTIONS", + "_APP_OPTIONS_FORCE_HTTPS", + "_APP_DOMAINS_NAMESERVERS" ] }, "mfaChallenge": { @@ -39170,6 +42582,11 @@ "user" ] }, + "resourceId": { + "type": "string", + "description": "Id of the resource to migrate.", + "x-example": "databaseId:collectionId" + }, "statusCounters": { "type": "object", "additionalProperties": true, @@ -39200,6 +42617,7 @@ "source", "destination", "resources", + "resourceId", "statusCounters", "resourceData", "errors" @@ -39274,26 +42692,6 @@ "size", "version" ] - }, - "firebaseProject": { - "description": "MigrationFirebaseProject", - "type": "object", - "properties": { - "projectId": { - "type": "string", - "description": "Project ID.", - "x-example": "my-project" - }, - "displayName": { - "type": "string", - "description": "Project display name.", - "x-example": "My Project" - } - }, - "required": [ - "projectId", - "displayName" - ] } }, "externalDocs": { diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 2c8e80c65e..41661b20ac 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.6.0", + "version": "1.7.0", "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", @@ -102,7 +102,7 @@ }, "x-appwrite": { "method": "get", - "weight": 9, + "weight": 10, "cookies": false, "type": "", "deprecated": false, @@ -117,9 +117,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -156,7 +153,7 @@ }, "x-appwrite": { "method": "create", - "weight": 8, + "weight": 9, "cookies": false, "type": "", "deprecated": false, @@ -171,9 +168,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -249,7 +243,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 34, + "weight": 35, "cookies": false, "type": "", "deprecated": false, @@ -264,9 +258,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -332,7 +323,7 @@ }, "x-appwrite": { "method": "listIdentities", - "weight": 57, + "weight": 58, "cookies": false, "type": "", "deprecated": false, @@ -347,9 +338,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/identities", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -397,7 +385,7 @@ }, "x-appwrite": { "method": "deleteIdentity", - "weight": 58, + "weight": 59, "cookies": false, "type": "", "deprecated": false, @@ -412,9 +400,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -463,7 +448,7 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 29, + "weight": 30, "cookies": false, "type": "", "deprecated": false, @@ -478,9 +463,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -516,7 +498,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 31, + "weight": 32, "cookies": false, "type": "", "deprecated": false, @@ -531,9 +513,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -586,7 +565,7 @@ }, "x-appwrite": { "method": "updateMFA", - "weight": 44, + "weight": 45, "cookies": false, "type": "", "deprecated": false, @@ -601,9 +580,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -662,7 +638,7 @@ }, "x-appwrite": { "method": "createMfaAuthenticator", - "weight": 46, + "weight": 47, "cookies": false, "type": "", "deprecated": false, @@ -677,9 +653,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -731,7 +704,7 @@ }, "x-appwrite": { "method": "updateMfaAuthenticator", - "weight": 47, + "weight": 48, "cookies": false, "type": "", "deprecated": false, @@ -746,9 +719,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -813,7 +783,7 @@ }, "x-appwrite": { "method": "deleteMfaAuthenticator", - "weight": 51, + "weight": 52, "cookies": false, "type": "", "deprecated": false, @@ -828,9 +798,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -884,7 +851,7 @@ }, "x-appwrite": { "method": "createMfaChallenge", - "weight": 52, + "weight": 53, "cookies": false, "type": "", "deprecated": false, @@ -899,9 +866,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -946,19 +910,24 @@ "consumes": [ "application\/json" ], - "produces": [], + "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": { - "204": { - "description": "No content" + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } } }, "x-appwrite": { "method": "updateMfaChallenge", - "weight": 53, + "weight": 54, "cookies": false, "type": "", "deprecated": false, @@ -973,9 +942,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1041,7 +1007,7 @@ }, "x-appwrite": { "method": "listMfaFactors", - "weight": 45, + "weight": 46, "cookies": false, "type": "", "deprecated": false, @@ -1056,9 +1022,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1097,7 +1060,7 @@ }, "x-appwrite": { "method": "getMfaRecoveryCodes", - "weight": 50, + "weight": 51, "cookies": false, "type": "", "deprecated": false, @@ -1112,9 +1075,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1151,7 +1111,7 @@ }, "x-appwrite": { "method": "createMfaRecoveryCodes", - "weight": 48, + "weight": 49, "cookies": false, "type": "", "deprecated": false, @@ -1166,9 +1126,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1205,7 +1162,7 @@ }, "x-appwrite": { "method": "updateMfaRecoveryCodes", - "weight": 49, + "weight": 50, "cookies": false, "type": "", "deprecated": false, @@ -1220,9 +1177,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1261,7 +1215,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 32, + "weight": 33, "cookies": false, "type": "", "deprecated": false, @@ -1276,9 +1230,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1337,7 +1288,7 @@ }, "x-appwrite": { "method": "updatePassword", - "weight": 33, + "weight": 34, "cookies": false, "type": "", "deprecated": false, @@ -1352,9 +1303,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1419,7 +1367,7 @@ }, "x-appwrite": { "method": "updatePhone", - "weight": 35, + "weight": 36, "cookies": false, "type": "", "deprecated": false, @@ -1434,9 +1382,6 @@ "server" ], "packaging": false, - "offline-model": "\/account", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1502,7 +1447,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 30, + "weight": 31, "cookies": false, "type": "", "deprecated": false, @@ -1517,9 +1462,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1556,7 +1498,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 36, + "weight": 37, "cookies": false, "type": "", "deprecated": false, @@ -1571,9 +1513,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/prefs", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1632,7 +1571,7 @@ }, "x-appwrite": { "method": "createRecovery", - "weight": 38, + "weight": 39, "cookies": false, "type": "", "deprecated": false, @@ -1650,9 +1589,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1716,7 +1652,7 @@ }, "x-appwrite": { "method": "updateRecovery", - "weight": 39, + "weight": 40, "cookies": false, "type": "", "deprecated": false, @@ -1731,9 +1667,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1806,7 +1739,7 @@ }, "x-appwrite": { "method": "listSessions", - "weight": 11, + "weight": 12, "cookies": false, "type": "", "deprecated": false, @@ -1821,9 +1754,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1855,7 +1785,7 @@ }, "x-appwrite": { "method": "deleteSessions", - "weight": 12, + "weight": 13, "cookies": false, "type": "", "deprecated": false, @@ -1870,9 +1800,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -1911,7 +1838,7 @@ }, "x-appwrite": { "method": "createAnonymousSession", - "weight": 17, + "weight": 18, "cookies": false, "type": "", "deprecated": false, @@ -1926,9 +1853,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -1964,7 +1888,7 @@ }, "x-appwrite": { "method": "createEmailPasswordSession", - "weight": 16, + "weight": 17, "cookies": false, "type": "", "deprecated": false, @@ -1979,9 +1903,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2044,7 +1965,7 @@ }, "x-appwrite": { "method": "updateMagicURLSession", - "weight": 26, + "weight": 27, "cookies": false, "type": "", "deprecated": true, @@ -2059,9 +1980,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2124,7 +2042,7 @@ }, "x-appwrite": { "method": "updatePhoneSession", - "weight": 27, + "weight": 28, "cookies": false, "type": "", "deprecated": true, @@ -2139,9 +2057,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2204,7 +2119,7 @@ }, "x-appwrite": { "method": "createSession", - "weight": 18, + "weight": 19, "cookies": false, "type": "", "deprecated": false, @@ -2219,9 +2134,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2284,7 +2196,7 @@ }, "x-appwrite": { "method": "getSession", - "weight": 13, + "weight": 14, "cookies": false, "type": "", "deprecated": false, @@ -2299,9 +2211,6 @@ "server" ], "packaging": false, - "offline-model": "\/account\/sessions", - "offline-key": "{sessionId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2348,7 +2257,7 @@ }, "x-appwrite": { "method": "updateSession", - "weight": 15, + "weight": 16, "cookies": false, "type": "", "deprecated": false, @@ -2363,9 +2272,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2407,7 +2313,7 @@ }, "x-appwrite": { "method": "deleteSession", - "weight": 14, + "weight": 15, "cookies": false, "type": "", "deprecated": false, @@ -2422,9 +2328,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2473,7 +2376,7 @@ }, "x-appwrite": { "method": "updateStatus", - "weight": 37, + "weight": 38, "cookies": false, "type": "", "deprecated": false, @@ -2488,9 +2391,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -2529,7 +2429,7 @@ }, "x-appwrite": { "method": "createEmailToken", - "weight": 25, + "weight": 26, "cookies": false, "type": "", "deprecated": false, @@ -2544,9 +2444,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2604,7 +2501,7 @@ "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. If you are on a mobile device you can leave the URL parameter empty, so that the login completion will be handled by your Appwrite instance by default.\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", + "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", @@ -2615,7 +2512,7 @@ }, "x-appwrite": { "method": "createMagicURLToken", - "weight": 24, + "weight": 25, "cookies": false, "type": "", "deprecated": false, @@ -2633,9 +2530,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2707,7 +2601,7 @@ }, "x-appwrite": { "method": "createOAuth2Token", - "weight": 23, + "weight": 24, "cookies": false, "type": "webAuth", "deprecated": false, @@ -2722,9 +2616,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2845,7 +2736,7 @@ }, "x-appwrite": { "method": "createPhoneToken", - "weight": 28, + "weight": 29, "cookies": false, "type": "", "deprecated": false, @@ -2863,9 +2754,6 @@ "client" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [] } @@ -2928,7 +2816,7 @@ }, "x-appwrite": { "method": "createVerification", - "weight": 40, + "weight": 41, "cookies": false, "type": "", "deprecated": false, @@ -2943,9 +2831,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3002,7 +2887,7 @@ }, "x-appwrite": { "method": "updateVerification", - "weight": 41, + "weight": 42, "cookies": false, "type": "", "deprecated": false, @@ -3017,9 +2902,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3085,7 +2967,7 @@ }, "x-appwrite": { "method": "createPhoneVerification", - "weight": 42, + "weight": 43, "cookies": false, "type": "", "deprecated": false, @@ -3103,9 +2985,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3142,7 +3021,7 @@ }, "x-appwrite": { "method": "updatePhoneVerification", - "weight": 43, + "weight": 44, "cookies": false, "type": "", "deprecated": false, @@ -3157,9 +3036,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3225,7 +3101,7 @@ }, "x-appwrite": { "method": "getBrowser", - "weight": 60, + "weight": 61, "cookies": false, "type": "location", "deprecated": false, @@ -3241,9 +3117,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3356,7 +3229,7 @@ }, "x-appwrite": { "method": "getCreditCard", - "weight": 59, + "weight": 60, "cookies": false, "type": "location", "deprecated": false, @@ -3372,9 +3245,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3391,7 +3261,7 @@ "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.", + "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", @@ -3411,7 +3281,8 @@ "union-china-pay", "visa", "mir", - "maestro" + "maestro", + "rupay" ], "x-enum-name": "CreditCard", "x-enum-keys": [ @@ -3430,7 +3301,8 @@ "Union China Pay", "Visa", "MIR", - "Maestro" + "Maestro", + "Rupay" ], "in": "path" }, @@ -3491,7 +3363,7 @@ }, "x-appwrite": { "method": "getFavicon", - "weight": 63, + "weight": 64, "cookies": false, "type": "location", "deprecated": false, @@ -3507,9 +3379,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -3560,7 +3429,7 @@ }, "x-appwrite": { "method": "getFlag", - "weight": 61, + "weight": 62, "cookies": false, "type": "location", "deprecated": false, @@ -3576,9 +3445,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4053,7 +3919,7 @@ }, "x-appwrite": { "method": "getImage", - "weight": 62, + "weight": 63, "cookies": false, "type": "location", "deprecated": false, @@ -4069,9 +3935,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4142,7 +4005,7 @@ }, "x-appwrite": { "method": "getInitials", - "weight": 65, + "weight": 66, "cookies": false, "type": "location", "deprecated": false, @@ -4158,9 +4021,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4239,7 +4099,7 @@ }, "x-appwrite": { "method": "getQR", - "weight": 64, + "weight": 65, "cookies": false, "type": "location", "deprecated": false, @@ -4255,9 +4115,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -4336,7 +4193,7 @@ }, "x-appwrite": { "method": "list", - "weight": 70, + "weight": 71, "cookies": false, "type": "", "deprecated": false, @@ -4350,9 +4207,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4411,7 +4265,7 @@ }, "x-appwrite": { "method": "create", - "weight": 69, + "weight": 70, "cookies": false, "type": "", "deprecated": false, @@ -4425,9 +4279,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4498,7 +4349,7 @@ }, "x-appwrite": { "method": "get", - "weight": 71, + "weight": 72, "cookies": false, "type": "", "deprecated": false, @@ -4512,9 +4363,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4560,7 +4408,7 @@ }, "x-appwrite": { "method": "update", - "weight": 73, + "weight": 74, "cookies": false, "type": "", "deprecated": false, @@ -4574,9 +4422,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4641,7 +4486,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 74, + "weight": 75, "cookies": false, "type": "", "deprecated": false, @@ -4655,9 +4500,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4705,7 +4547,7 @@ }, "x-appwrite": { "method": "listCollections", - "weight": 76, + "weight": 77, "cookies": false, "type": "", "deprecated": false, @@ -4719,9 +4561,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4788,7 +4627,7 @@ }, "x-appwrite": { "method": "createCollection", - "weight": 75, + "weight": 76, "cookies": false, "type": "", "deprecated": false, @@ -4802,9 +4641,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4898,7 +4734,7 @@ }, "x-appwrite": { "method": "getCollection", - "weight": 77, + "weight": 78, "cookies": false, "type": "", "deprecated": false, @@ -4912,9 +4748,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -4968,7 +4801,7 @@ }, "x-appwrite": { "method": "updateCollection", - "weight": 79, + "weight": 80, "cookies": false, "type": "", "deprecated": false, @@ -4982,9 +4815,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5072,7 +4902,7 @@ }, "x-appwrite": { "method": "deleteCollection", - "weight": 80, + "weight": 81, "cookies": false, "type": "", "deprecated": false, @@ -5086,9 +4916,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5144,7 +4971,7 @@ }, "x-appwrite": { "method": "listAttributes", - "weight": 91, + "weight": 92, "cookies": false, "type": "", "deprecated": false, @@ -5158,9 +4985,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5228,7 +5052,7 @@ }, "x-appwrite": { "method": "createBooleanAttribute", - "weight": 88, + "weight": 89, "cookies": false, "type": "", "deprecated": false, @@ -5242,9 +5066,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5320,7 +5141,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5335,7 +5158,7 @@ }, "x-appwrite": { "method": "updateBooleanAttribute", - "weight": 100, + "weight": 101, "cookies": false, "type": "", "deprecated": false, @@ -5349,9 +5172,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5446,7 +5266,7 @@ }, "x-appwrite": { "method": "createDatetimeAttribute", - "weight": 89, + "weight": 90, "cookies": false, "type": "", "deprecated": false, @@ -5460,9 +5280,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5538,7 +5355,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5553,7 +5372,7 @@ }, "x-appwrite": { "method": "updateDatetimeAttribute", - "weight": 101, + "weight": 102, "cookies": false, "type": "", "deprecated": false, @@ -5567,9 +5386,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5664,7 +5480,7 @@ }, "x-appwrite": { "method": "createEmailAttribute", - "weight": 82, + "weight": 83, "cookies": false, "type": "", "deprecated": false, @@ -5678,9 +5494,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5756,7 +5569,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5771,7 +5586,7 @@ }, "x-appwrite": { "method": "updateEmailAttribute", - "weight": 94, + "weight": 95, "cookies": false, "type": "", "deprecated": false, @@ -5785,9 +5600,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5882,7 +5694,7 @@ }, "x-appwrite": { "method": "createEnumAttribute", - "weight": 83, + "weight": 84, "cookies": false, "type": "", "deprecated": false, @@ -5896,9 +5708,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -5984,7 +5793,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -5999,7 +5810,7 @@ }, "x-appwrite": { "method": "updateEnumAttribute", - "weight": 95, + "weight": 96, "cookies": false, "type": "", "deprecated": false, @@ -6013,9 +5824,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6120,7 +5928,7 @@ }, "x-appwrite": { "method": "createFloatAttribute", - "weight": 87, + "weight": 88, "cookies": false, "type": "", "deprecated": false, @@ -6134,9 +5942,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6224,7 +6029,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6239,7 +6046,7 @@ }, "x-appwrite": { "method": "updateFloatAttribute", - "weight": 99, + "weight": 100, "cookies": false, "type": "", "deprecated": false, @@ -6253,9 +6060,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6331,8 +6135,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6364,7 +6166,7 @@ }, "x-appwrite": { "method": "createIntegerAttribute", - "weight": 86, + "weight": 87, "cookies": false, "type": "", "deprecated": false, @@ -6378,9 +6180,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6468,7 +6267,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6483,7 +6284,7 @@ }, "x-appwrite": { "method": "updateIntegerAttribute", - "weight": 98, + "weight": 99, "cookies": false, "type": "", "deprecated": false, @@ -6497,9 +6298,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6575,8 +6373,6 @@ }, "required": [ "required", - "min", - "max", "default" ] } @@ -6608,7 +6404,7 @@ }, "x-appwrite": { "method": "createIpAttribute", - "weight": 84, + "weight": 85, "cookies": false, "type": "", "deprecated": false, @@ -6622,9 +6418,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6700,7 +6493,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -6715,7 +6510,7 @@ }, "x-appwrite": { "method": "updateIpAttribute", - "weight": 96, + "weight": 97, "cookies": false, "type": "", "deprecated": false, @@ -6729,9 +6524,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6826,7 +6618,7 @@ }, "x-appwrite": { "method": "createRelationshipAttribute", - "weight": 90, + "weight": 91, "cookies": false, "type": "", "deprecated": false, @@ -6840,9 +6632,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -6962,7 +6751,7 @@ }, "x-appwrite": { "method": "createStringAttribute", - "weight": 81, + "weight": 82, "cookies": false, "type": "", "deprecated": false, @@ -6976,9 +6765,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7067,7 +6853,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7082,7 +6870,7 @@ }, "x-appwrite": { "method": "updateStringAttribute", - "weight": 93, + "weight": 94, "cookies": false, "type": "", "deprecated": false, @@ -7096,9 +6884,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7199,7 +6984,7 @@ }, "x-appwrite": { "method": "createUrlAttribute", - "weight": 85, + "weight": 86, "cookies": false, "type": "", "deprecated": false, @@ -7213,9 +6998,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7291,7 +7073,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7306,7 +7090,7 @@ }, "x-appwrite": { "method": "updateUrlAttribute", - "weight": 97, + "weight": 98, "cookies": false, "type": "", "deprecated": false, @@ -7320,9 +7104,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7448,7 +7229,7 @@ }, "x-appwrite": { "method": "getAttribute", - "weight": 92, + "weight": 93, "cookies": false, "type": "", "deprecated": false, @@ -7462,9 +7243,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7520,7 +7298,7 @@ }, "x-appwrite": { "method": "deleteAttribute", - "weight": 103, + "weight": 104, "cookies": false, "type": "", "deprecated": false, @@ -7534,9 +7312,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7582,7 +7357,9 @@ "consumes": [ "application\/json" ], - "produces": [], + "produces": [ + "application\/json" + ], "tags": [ "databases" ], @@ -7597,7 +7374,7 @@ }, "x-appwrite": { "method": "updateRelationshipAttribute", - "weight": 102, + "weight": 103, "cookies": false, "type": "", "deprecated": false, @@ -7611,9 +7388,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -7704,7 +7478,7 @@ }, "x-appwrite": { "method": "listDocuments", - "weight": 109, + "weight": 110, "cookies": false, "type": "", "deprecated": false, @@ -7720,9 +7494,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7779,7 +7550,7 @@ "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.", + "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.\n", "responses": { "201": { "description": "Document", @@ -7790,7 +7561,7 @@ }, "x-appwrite": { "method": "createDocument", - "weight": 108, + "weight": 109, "cookies": false, "type": "", "deprecated": false, @@ -7806,9 +7577,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7900,7 +7668,7 @@ }, "x-appwrite": { "method": "getDocument", - "weight": 110, + "weight": 111, "cookies": false, "type": "", "deprecated": false, @@ -7916,9 +7684,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -7994,7 +7759,7 @@ }, "x-appwrite": { "method": "updateDocument", - "weight": 112, + "weight": 113, "cookies": false, "type": "", "deprecated": false, @@ -8010,9 +7775,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8095,7 +7857,7 @@ }, "x-appwrite": { "method": "deleteDocument", - "weight": 113, + "weight": 114, "cookies": false, "type": "", "deprecated": false, @@ -8111,9 +7873,6 @@ "server" ], "packaging": false, - "offline-model": "\/databases\/{databaseId}\/collections\/{collectionId}\/documents", - "offline-key": "{documentId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -8179,7 +7938,7 @@ }, "x-appwrite": { "method": "listIndexes", - "weight": 105, + "weight": 106, "cookies": false, "type": "", "deprecated": false, @@ -8193,9 +7952,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8261,7 +8017,7 @@ }, "x-appwrite": { "method": "createIndex", - "weight": 104, + "weight": 105, "cookies": false, "type": "", "deprecated": false, @@ -8275,9 +8031,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8384,7 +8137,7 @@ }, "x-appwrite": { "method": "getIndex", - "weight": 106, + "weight": 107, "cookies": false, "type": "", "deprecated": false, @@ -8398,9 +8151,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8456,7 +8206,7 @@ }, "x-appwrite": { "method": "deleteIndex", - "weight": 107, + "weight": 108, "cookies": false, "type": "", "deprecated": false, @@ -8470,9 +8220,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8535,12 +8282,12 @@ }, "x-appwrite": { "method": "list", - "weight": 289, + "weight": 368, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/list-functions.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}", @@ -8549,9 +8296,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8566,7 +8310,7 @@ "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, deployment, schedule, scheduleNext, schedulePrevious, timeout, entrypoint, commands, installationId", + "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", @@ -8610,12 +8354,12 @@ }, "x-appwrite": { "method": "create", - "weight": 288, + "weight": 365, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/create-function.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}", @@ -8624,9 +8368,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8684,6 +8425,7 @@ "python-3.11", "python-3.12", "python-ml-3.11", + "python-ml-3.12", "deno-1.21", "deno-1.24", "deno-1.35", @@ -8694,6 +8436,7 @@ "dart-2.16", "dart-2.17", "dart-2.18", + "dart-2.19", "dart-3.0", "dart-3.1", "dart-3.3", @@ -8720,7 +8463,10 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29" ], "x-enum-name": null, "x-enum-keys": [] @@ -8763,7 +8509,7 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "default": true, "x-example": false }, @@ -8818,30 +8564,6 @@ "default": "", "x-example": "<PROVIDER_ROOT_DIRECTORY>" }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "default": "", - "x-example": "<TEMPLATE_REPOSITORY>" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "default": "", - "x-example": "<TEMPLATE_OWNER>" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "default": "", - "x-example": "<TEMPLATE_ROOT_DIRECTORY>" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "default": "", - "x-example": "<TEMPLATE_VERSION>" - }, "specification": { "type": "string", "description": "Runtime specification for the function and builds.", @@ -8883,23 +8605,20 @@ }, "x-appwrite": { "method": "listRuntimes", - "weight": 290, + "weight": 370, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-runtimes.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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": "functions.read", + "scope": "public", "platforms": [ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8915,7 +8634,7 @@ }, "\/functions\/specifications": { "get": { - "summary": "List available function runtime specifications", + "summary": "List specifications", "operationId": "functionsListSpecifications", "consumes": [ "application\/json" @@ -8926,7 +8645,7 @@ "tags": [ "functions" ], - "description": "List allowed function specifications for this instance.\n", + "description": "List allowed function specifications for this instance.", "responses": { "200": { "description": "Specifications List", @@ -8937,12 +8656,12 @@ }, "x-appwrite": { "method": "listSpecifications", - "weight": 291, + "weight": 371, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-specifications.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -8952,9 +8671,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -8992,12 +8708,12 @@ }, "x-appwrite": { "method": "get", - "weight": 292, + "weight": 366, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-function.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}", @@ -9006,9 +8722,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9054,12 +8767,12 @@ }, "x-appwrite": { "method": "update", - "weight": 295, + "weight": 367, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/update.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-function.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}", @@ -9068,9 +8781,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9130,6 +8840,7 @@ "python-3.11", "python-3.12", "python-ml-3.11", + "python-ml-3.12", "deno-1.21", "deno-1.24", "deno-1.35", @@ -9140,6 +8851,7 @@ "dart-2.16", "dart-2.17", "dart-2.18", + "dart-2.19", "dart-3.0", "dart-3.1", "dart-3.3", @@ -9166,7 +8878,10 @@ "bun-1.0", "bun-1.1", "go-1.23", - "static-1" + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29" ], "x-enum-name": null, "x-enum-keys": [] @@ -9209,7 +8924,7 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "default": true, "x-example": false }, @@ -9297,12 +9012,12 @@ }, "x-appwrite": { "method": "delete", - "weight": 298, + "weight": 369, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/delete-function.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}", @@ -9311,9 +9026,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9337,6 +9049,85 @@ ] } }, + "\/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", + "weight": 374, + "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", @@ -9350,7 +9141,7 @@ "tags": [ "functions" ], - "description": "Get a list of all the project's code deployments. You can use the query params to filter your results.", + "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", @@ -9361,12 +9152,12 @@ }, "x-appwrite": { "method": "listDeployments", - "weight": 300, + "weight": 375, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-deployments.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9375,9 +9166,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9400,7 +9188,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: size, buildId, activate, entrypoint, commands, type, size", + "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", @@ -9444,12 +9232,12 @@ }, "x-appwrite": { "method": "createDeployment", - "weight": 299, + "weight": 372, "cookies": false, "type": "upload", "deprecated": false, "demo": "functions\/create-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9458,9 +9246,6 @@ "server" ], "packaging": true, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9515,10 +9300,10 @@ ] } }, - "\/functions\/{functionId}\/deployments\/{deploymentId}": { - "get": { - "summary": "Get deployment", - "operationId": "functionsGetDeployment", + "\/functions\/{functionId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "functionsCreateDuplicateDeployment", "consumes": [ "application\/json" ], @@ -9528,9 +9313,9 @@ "tags": [ "functions" ], - "description": "Get a code deployment by its unique ID.", + "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": { - "200": { + "202": { "description": "Deployment", "schema": { "$ref": "#\/definitions\/deployment" @@ -9538,24 +9323,21 @@ } }, "x-appwrite": { - "method": "getDeployment", - "weight": 301, + "method": "createDuplicateDeployment", + "weight": 380, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/get-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/get-deployment.md", + "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.read", + "scope": "functions.write", "platforms": [ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9577,18 +9359,36 @@ "in": "path" }, { - "name": "deploymentId", - "description": "Deployment ID.", - "required": true, - "type": "string", - "x-example": "<DEPLOYMENT_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" + ] + } } ] - }, - "patch": { - "summary": "Update deployment", - "operationId": "functionsUpdateDeployment", + } + }, + "\/functions\/{functionId}\/deployments\/template": { + "post": { + "summary": "Create template deployment", + "operationId": "functionsCreateTemplateDeployment", "consumes": [ "application\/json" ], @@ -9598,23 +9398,23 @@ "tags": [ "functions" ], - "description": "Update the function code deployment ID using the unique function ID. Use this endpoint to switch the code deployment that should be executed by the execution endpoint.", + "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": { - "200": { - "description": "Function", + "202": { + "description": "Deployment", "schema": { - "$ref": "#\/definitions\/function" + "$ref": "#\/definitions\/deployment" } } }, "x-appwrite": { - "method": "updateDeployment", - "weight": 297, + "method": "createTemplateDeployment", + "weight": 377, "cookies": false, "type": "", "deprecated": false, - "demo": "functions\/update-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/functions\/update-function-deployment.md", + "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}", @@ -9623,9 +9423,210 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", + "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", + "weight": 378, + "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": [ + "application\/json" + ], + "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", + "weight": 373, + "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": [] @@ -9674,12 +9675,12 @@ }, "x-appwrite": { "method": "deleteDeployment", - "weight": 302, + "weight": 376, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-deployment.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9688,161 +9689,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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}\/build": { - "post": { - "summary": "Rebuild deployment", - "operationId": "functionsCreateBuild", - "consumes": [ - "application\/json" - ], - "produces": [], - "tags": [ - "functions" - ], - "description": "", - "responses": { - "204": { - "description": "No content" - } - }, - "x-appwrite": { - "method": "createBuild", - "weight": 303, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "functions\/create-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "functions.write", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "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" - }, - { - "name": "payload", - "in": "body", - "schema": { - "type": "object", - "properties": { - "buildId": { - "type": "string", - "description": "Build unique ID.", - "default": "", - "x-example": "<BUILD_ID>" - } - } - } - } - ] - }, - "patch": { - "summary": "Cancel deployment", - "operationId": "functionsUpdateDeploymentBuild", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "functions" - ], - "description": "", - "responses": { - "200": { - "description": "Build", - "schema": { - "$ref": "#\/definitions\/build" - } - } - }, - "x-appwrite": { - "method": "updateDeploymentBuild", - "weight": 304, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "functions\/update-deployment-build.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "functions.write", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9887,7 +9733,7 @@ "tags": [ "functions" ], - "description": "Get a Deployment's contents by its unique ID. This endpoint supports range requests for partial or streaming file download.", + "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", @@ -9898,12 +9744,12 @@ }, "x-appwrite": { "method": "getDeploymentDownload", - "weight": 296, + "weight": 379, "cookies": false, "type": "location", "deprecated": false, "demo": "functions\/get-deployment-download.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9913,9 +9759,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -9928,6 +9771,90 @@ "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", + "weight": 381, + "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", @@ -9972,12 +9899,12 @@ }, "x-appwrite": { "method": "listExecutions", - "weight": 306, + "weight": 384, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-executions.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -9988,9 +9915,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10024,15 +9948,6 @@ }, "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" } ] }, @@ -10059,12 +9974,12 @@ }, "x-appwrite": { "method": "createExecution", - "weight": 305, + "weight": 382, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10075,9 +9990,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10182,12 +10094,12 @@ }, "x-appwrite": { "method": "getExecution", - "weight": 307, + "weight": 383, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10198,9 +10110,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -10243,7 +10152,7 @@ "tags": [ "functions" ], - "description": "Delete a function execution by its unique ID.\n", + "description": "Delete a function execution by its unique ID.", "responses": { "204": { "description": "No content" @@ -10251,12 +10160,12 @@ }, "x-appwrite": { "method": "deleteExecution", - "weight": 308, + "weight": 385, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-execution.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10265,9 +10174,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10323,12 +10229,12 @@ }, "x-appwrite": { "method": "listVariables", - "weight": 310, + "weight": 390, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/list-variables.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10337,9 +10243,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10385,12 +10288,12 @@ }, "x-appwrite": { "method": "createVariable", - "weight": 309, + "weight": 388, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/create-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10399,9 +10302,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10439,6 +10339,12 @@ "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": [ @@ -10474,12 +10380,12 @@ }, "x-appwrite": { "method": "getVariable", - "weight": 311, + "weight": 389, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/get-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10488,9 +10394,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10544,12 +10447,12 @@ }, "x-appwrite": { "method": "updateVariable", - "weight": 312, + "weight": 391, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/update-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10558,9 +10461,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10606,6 +10506,12 @@ "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": [ @@ -10633,12 +10539,12 @@ }, "x-appwrite": { "method": "deleteVariable", - "weight": 313, + "weight": 392, "cookies": false, "type": "", "deprecated": false, "demo": "functions\/delete-variable.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -10647,9 +10553,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10705,7 +10608,7 @@ }, "x-appwrite": { "method": "query", - "weight": 331, + "weight": 303, "cookies": false, "type": "graphql", "deprecated": false, @@ -10721,9 +10624,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10783,7 +10683,7 @@ }, "x-appwrite": { "method": "mutation", - "weight": 330, + "weight": 302, "cookies": false, "type": "graphql", "deprecated": false, @@ -10799,9 +10699,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10861,7 +10758,7 @@ }, "x-appwrite": { "method": "get", - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -10875,9 +10772,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10915,7 +10809,7 @@ }, "x-appwrite": { "method": "getAntivirus", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -10929,9 +10823,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -10969,7 +10860,7 @@ }, "x-appwrite": { "method": "getCache", - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -10983,9 +10874,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11037,9 +10925,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11086,7 +10971,7 @@ }, "x-appwrite": { "method": "getDB", - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -11100,9 +10985,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11154,63 +11036,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", - "auth": { - "Project": [], - "Key": [] - } - }, - "security": [ - { - "Project": [], - "Key": [] - } - ] - } - }, - "\/health\/queue": { - "get": { - "summary": "Get queue", - "operationId": "healthGetQueue", - "consumes": [ - "application\/json" - ], - "produces": [ - "application\/json" - ], - "tags": [ - "health" - ], - "description": "Check the Appwrite queue messaging servers are up and connection is successful.", - "responses": { - "200": { - "description": "Health Status", - "schema": { - "$ref": "#\/definitions\/healthStatus" - } - } - }, - "x-appwrite": { - "method": "getQueue", - "weight": 129, - "cookies": false, - "type": "", - "deprecated": false, - "demo": "health\/get-queue.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue.md", - "rate-limit": 0, - "rate-time": 3600, - "rate-key": "url:{url},ip:{ip}", - "scope": "health.read", - "platforms": [ - "server" - ], - "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11262,9 +11087,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11327,9 +11149,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11392,9 +11211,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11466,9 +11282,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11517,7 +11330,7 @@ }, "x-appwrite": { "method": "getFailedJobs", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -11531,9 +11344,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11558,8 +11368,9 @@ "v1-audits", "v1-mails", "v1-functions", - "v1-usage", - "v1-usage-dump", + "v1-stats-resources", + "v1-stats-usage", + "v1-stats-usage-dump", "v1-webhooks", "v1-certificates", "v1-builds", @@ -11620,9 +11431,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11685,9 +11493,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11750,9 +11555,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11815,9 +11617,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11880,9 +11679,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11907,9 +11703,71 @@ ] } }, - "\/health\/queue\/usage": { + "\/health\/queue\/stats-resources": { "get": { - "summary": "Get usage queue", + "summary": "Get stats resources queue", + "operationId": "healthGetQueueStatsResources", + "consumes": [ + "application\/json" + ], + "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", + "weight": 143, + "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": [ "application\/json" @@ -11931,12 +11789,12 @@ }, "x-appwrite": { "method": "getQueueUsage", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, "demo": "health\/get-queue-usage.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/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}", @@ -11945,9 +11803,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -11972,10 +11827,10 @@ ] } }, - "\/health\/queue\/usage-dump": { + "\/health\/queue\/stats-usage-dump": { "get": { "summary": "Get usage dump queue", - "operationId": "healthGetQueueUsageDump", + "operationId": "healthGetQueueStatsUsageDump", "consumes": [ "application\/json" ], @@ -11995,13 +11850,13 @@ } }, "x-appwrite": { - "method": "getQueueUsageDump", - "weight": 144, + "method": "getQueueStatsUsageDump", + "weight": 145, "cookies": false, "type": "", "deprecated": false, - "demo": "health\/get-queue-usage-dump.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-usage-dump.md", + "demo": "health\/get-queue-stats-usage-dump.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage-dump.md", "rate-limit": 0, "rate-time": 3600, "rate-key": "url:{url},ip:{ip}", @@ -12010,9 +11865,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12075,9 +11927,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12126,7 +11975,7 @@ }, "x-appwrite": { "method": "getStorage", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -12140,9 +11989,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12180,7 +12026,7 @@ }, "x-appwrite": { "method": "getStorageLocal", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -12194,9 +12040,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12248,9 +12091,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12288,7 +12128,7 @@ }, "x-appwrite": { "method": "get", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -12304,9 +12144,6 @@ "server" ], "packaging": false, - "offline-model": "\/localed", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12346,7 +12183,7 @@ }, "x-appwrite": { "method": "listCodes", - "weight": 118, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -12362,9 +12199,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/localeCode", - "offline-key": "current", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -12404,7 +12238,7 @@ }, "x-appwrite": { "method": "listContinents", - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -12420,9 +12254,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/continents", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12462,7 +12293,7 @@ }, "x-appwrite": { "method": "listCountries", - "weight": 119, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -12478,9 +12309,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12520,7 +12348,7 @@ }, "x-appwrite": { "method": "listCountriesEU", - "weight": 120, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -12536,9 +12364,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/eu", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12578,7 +12403,7 @@ }, "x-appwrite": { "method": "listCountriesPhones", - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -12594,9 +12419,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/countries\/phones", - "offline-key": "", - "offline-response-key": "countryCode", "auth": { "Project": [], "Session": [] @@ -12636,7 +12458,7 @@ }, "x-appwrite": { "method": "listCurrencies", - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -12652,9 +12474,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/currencies", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12694,7 +12513,7 @@ }, "x-appwrite": { "method": "listLanguages", - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -12710,9 +12529,6 @@ "server" ], "packaging": false, - "offline-model": "\/locale\/languages", - "offline-key": "", - "offline-response-key": "code", "auth": { "Project": [], "Session": [] @@ -12752,7 +12568,7 @@ }, "x-appwrite": { "method": "listMessages", - "weight": 390, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -12767,9 +12583,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12830,7 +12643,7 @@ }, "x-appwrite": { "method": "createEmail", - "weight": 387, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -12845,9 +12658,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -12980,7 +12790,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -12991,7 +12801,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 394, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -13006,9 +12816,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13149,7 +12956,7 @@ }, "x-appwrite": { "method": "createPush", - "weight": 389, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -13164,9 +12971,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13194,13 +12998,13 @@ "title": { "type": "string", "description": "Title for push notification.", - "default": null, + "default": "", "x-example": "<TITLE>" }, "body": { "type": "string", "description": "Body for push notification.", - "default": null, + "default": "", "x-example": "<BODY>" }, "topics": { @@ -13232,7 +13036,7 @@ }, "data": { "type": "object", - "description": "Additional Data for push notification.", + "description": "Additional key-value pair data for push notification.", "default": {}, "x-example": "{}" }, @@ -13256,7 +13060,7 @@ }, "sound": { "type": "string", - "description": "Sound for push notification. Available only for Android and IOS Platform.", + "description": "Sound for push notification. Available only for Android and iOS Platform.", "default": "", "x-example": "<SOUND>" }, @@ -13273,10 +13077,10 @@ "x-example": "<TAG>" }, "badge": { - "type": "string", - "description": "Badge for push notification. Available only for IOS Platform.", - "default": "", - "x-example": "<BADGE>" + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "default": -1, + "x-example": null }, "draft": { "type": "boolean", @@ -13289,12 +13093,34 @@ "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", - "title", - "body" + "messageId" ] } } @@ -13314,7 +13140,7 @@ "tags": [ "messaging" ], - "description": "Update a push notification by its unique ID.\n", + "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", @@ -13325,7 +13151,7 @@ }, "x-appwrite": { "method": "updatePush", - "weight": 396, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -13340,9 +13166,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13467,6 +13290,30 @@ "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": [] } } } @@ -13498,7 +13345,7 @@ }, "x-appwrite": { "method": "createSms", - "weight": 388, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -13513,9 +13360,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13608,7 +13452,7 @@ "tags": [ "messaging" ], - "description": "Update an email message by its unique ID.\n", + "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", @@ -13619,12 +13463,12 @@ }, "x-appwrite": { "method": "updateSms", - "weight": 395, + "weight": 362, "cookies": false, "type": "", "deprecated": false, "demo": "messaging\/update-sms.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.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}", @@ -13634,9 +13478,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13738,7 +13579,7 @@ }, "x-appwrite": { "method": "getMessage", - "weight": 393, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -13753,9 +13594,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13784,9 +13622,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -13798,7 +13634,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 397, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -13813,9 +13649,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13863,7 +13696,7 @@ }, "x-appwrite": { "method": "listMessageLogs", - "weight": 391, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -13878,9 +13711,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -13940,7 +13770,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 392, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -13955,9 +13785,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14017,7 +13844,7 @@ }, "x-appwrite": { "method": "listProviders", - "weight": 362, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -14032,9 +13859,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14095,7 +13919,7 @@ }, "x-appwrite": { "method": "createApnsProvider", - "weight": 361, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -14110,9 +13934,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14213,7 +14034,7 @@ }, "x-appwrite": { "method": "updateApnsProvider", - "weight": 374, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -14228,9 +14049,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14329,7 +14147,7 @@ }, "x-appwrite": { "method": "createFcmProvider", - "weight": 360, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -14344,9 +14162,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14423,7 +14238,7 @@ }, "x-appwrite": { "method": "updateFcmProvider", - "weight": 373, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -14438,9 +14253,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14515,7 +14327,7 @@ }, "x-appwrite": { "method": "createMailgunProvider", - "weight": 352, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -14530,9 +14342,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14645,7 +14454,7 @@ }, "x-appwrite": { "method": "updateMailgunProvider", - "weight": 365, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -14660,9 +14469,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14773,7 +14579,7 @@ }, "x-appwrite": { "method": "createMsg91Provider", - "weight": 355, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -14788,9 +14594,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14879,7 +14682,7 @@ }, "x-appwrite": { "method": "updateMsg91Provider", - "weight": 368, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -14894,9 +14697,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -14983,7 +14783,7 @@ }, "x-appwrite": { "method": "createSendgridProvider", - "weight": 353, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -14998,9 +14798,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15101,7 +14898,7 @@ }, "x-appwrite": { "method": "updateSendgridProvider", - "weight": 366, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -15116,9 +14913,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15217,7 +15011,7 @@ }, "x-appwrite": { "method": "createSmtpProvider", - "weight": 354, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -15232,9 +15026,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15379,7 +15170,7 @@ }, "x-appwrite": { "method": "updateSmtpProvider", - "weight": 367, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -15394,9 +15185,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15538,7 +15326,7 @@ }, "x-appwrite": { "method": "createTelesignProvider", - "weight": 356, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -15553,9 +15341,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15644,7 +15429,7 @@ }, "x-appwrite": { "method": "updateTelesignProvider", - "weight": 369, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -15659,9 +15444,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15748,7 +15530,7 @@ }, "x-appwrite": { "method": "createTextmagicProvider", - "weight": 357, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -15763,9 +15545,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15854,7 +15633,7 @@ }, "x-appwrite": { "method": "updateTextmagicProvider", - "weight": 370, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -15869,9 +15648,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -15958,7 +15734,7 @@ }, "x-appwrite": { "method": "createTwilioProvider", - "weight": 358, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -15973,9 +15749,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16064,7 +15837,7 @@ }, "x-appwrite": { "method": "updateTwilioProvider", - "weight": 371, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -16079,9 +15852,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16168,7 +15938,7 @@ }, "x-appwrite": { "method": "createVonageProvider", - "weight": 359, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -16183,9 +15953,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16274,7 +16041,7 @@ }, "x-appwrite": { "method": "updateVonageProvider", - "weight": 372, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -16289,9 +16056,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16378,7 +16142,7 @@ }, "x-appwrite": { "method": "getProvider", - "weight": 364, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -16393,9 +16157,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16424,9 +16185,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -16438,7 +16197,7 @@ }, "x-appwrite": { "method": "deleteProvider", - "weight": 375, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -16453,9 +16212,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16503,7 +16259,7 @@ }, "x-appwrite": { "method": "listProviderLogs", - "weight": 363, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -16518,9 +16274,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16580,7 +16333,7 @@ }, "x-appwrite": { "method": "listSubscriberLogs", - "weight": 384, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16595,9 +16348,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16657,7 +16407,7 @@ }, "x-appwrite": { "method": "listTopics", - "weight": 377, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -16672,9 +16422,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16733,7 +16480,7 @@ }, "x-appwrite": { "method": "createTopic", - "weight": 376, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -16748,9 +16495,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16826,7 +16570,7 @@ }, "x-appwrite": { "method": "getTopic", - "weight": 379, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -16841,9 +16585,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16889,7 +16630,7 @@ }, "x-appwrite": { "method": "updateTopic", - "weight": 380, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16904,9 +16645,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -16959,9 +16697,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -16973,7 +16709,7 @@ }, "x-appwrite": { "method": "deleteTopic", - "weight": 381, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16988,9 +16724,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17038,7 +16771,7 @@ }, "x-appwrite": { "method": "listTopicLogs", - "weight": 378, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -17053,9 +16786,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17115,7 +16845,7 @@ }, "x-appwrite": { "method": "listSubscribers", - "weight": 383, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -17130,9 +16860,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17199,7 +16926,7 @@ }, "x-appwrite": { "method": "createSubscriber", - "weight": 382, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -17216,9 +16943,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -17293,7 +17017,7 @@ }, "x-appwrite": { "method": "getSubscriber", - "weight": 385, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17308,9 +17032,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17347,9 +17068,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "messaging" ], @@ -17361,7 +17080,7 @@ }, "x-appwrite": { "method": "deleteSubscriber", - "weight": 386, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -17378,9 +17097,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "JWT": [] @@ -17414,6 +17130,2240 @@ ] } }, + "\/sites": { + "get": { + "summary": "List sites", + "operationId": "sitesList", + "consumes": [ + "application\/json" + ], + "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", + "weight": 397, + "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", + "weight": 395, + "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", + "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", + "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" + ], + "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": [ + "application\/json" + ], + "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", + "weight": 400, + "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": [ + "application\/json" + ], + "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", + "weight": 423, + "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": [ + "application\/json" + ], + "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", + "weight": 396, + "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", + "weight": 398, + "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", + "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", + "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" + ], + "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", + "weight": 399, + "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", + "weight": 406, + "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": [ + "application\/json" + ], + "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", + "weight": 405, + "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", + "weight": 401, + "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", + "weight": 409, + "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", + "weight": 402, + "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", + "weight": 403, + "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": [ + "application\/json" + ], + "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", + "weight": 404, + "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", + "weight": 407, + "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": "Download deployment", + "operationId": "sitesGetDeploymentDownload", + "consumes": [ + "application\/json" + ], + "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", + "weight": 408, + "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", + "weight": 410, + "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": [ + "application\/json" + ], + "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", + "weight": 412, + "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": [ + "application\/json" + ], + "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", + "weight": 411, + "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", + "weight": 413, + "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": [ + "application\/json" + ], + "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", + "weight": 416, + "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", + "weight": 414, + "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": [ + "application\/json" + ], + "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", + "weight": 415, + "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", + "weight": 417, + "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", + "weight": 418, + "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", @@ -17438,7 +19388,7 @@ }, "x-appwrite": { "method": "listBuckets", - "weight": 203, + "weight": 204, "cookies": false, "type": "", "deprecated": false, @@ -17452,9 +19402,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17513,7 +19460,7 @@ }, "x-appwrite": { "method": "createBucket", - "weight": 202, + "weight": 203, "cookies": false, "type": "", "deprecated": false, @@ -17527,9 +19474,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17655,7 +19599,7 @@ }, "x-appwrite": { "method": "getBucket", - "weight": 204, + "weight": 205, "cookies": false, "type": "", "deprecated": false, @@ -17669,9 +19613,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17717,7 +19658,7 @@ }, "x-appwrite": { "method": "updateBucket", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -17731,9 +19672,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17853,7 +19791,7 @@ }, "x-appwrite": { "method": "deleteBucket", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -17867,9 +19805,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -17917,7 +19852,7 @@ }, "x-appwrite": { "method": "listFiles", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -17933,9 +19868,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18004,7 +19936,7 @@ }, "x-appwrite": { "method": "createFile", - "weight": 207, + "weight": 208, "cookies": false, "type": "upload", "deprecated": false, @@ -18020,9 +19952,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18100,7 +20029,7 @@ }, "x-appwrite": { "method": "getFile", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -18116,9 +20045,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18174,7 +20100,7 @@ }, "x-appwrite": { "method": "updateFile", - "weight": 214, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -18190,9 +20116,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18267,7 +20190,7 @@ }, "x-appwrite": { "method": "deleteFile", - "weight": 215, + "weight": 216, "cookies": false, "type": "", "deprecated": false, @@ -18283,9 +20206,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18343,7 +20263,7 @@ }, "x-appwrite": { "method": "getFileDownload", - "weight": 211, + "weight": 212, "cookies": false, "type": "location", "deprecated": false, @@ -18359,9 +20279,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18419,7 +20336,7 @@ }, "x-appwrite": { "method": "getFilePreview", - "weight": 210, + "weight": 211, "cookies": false, "type": "location", "deprecated": false, @@ -18435,9 +20352,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18588,6 +20502,7 @@ "gif", "png", "webp", + "heic", "avif" ], "x-enum-name": "ImageFormat", @@ -18622,7 +20537,7 @@ }, "x-appwrite": { "method": "getFileView", - "weight": 212, + "weight": 213, "cookies": false, "type": "location", "deprecated": false, @@ -18638,9 +20553,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18698,7 +20610,7 @@ }, "x-appwrite": { "method": "list", - "weight": 219, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -18714,9 +20626,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18777,7 +20686,7 @@ }, "x-appwrite": { "method": "create", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -18793,9 +20702,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18873,7 +20779,7 @@ }, "x-appwrite": { "method": "get", - "weight": 220, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -18889,9 +20795,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -18939,7 +20842,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -18955,9 +20858,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams", - "offline-key": "{teamId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19018,7 +20918,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -19034,9 +20934,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19086,7 +20983,7 @@ }, "x-appwrite": { "method": "listMemberships", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -19102,9 +20999,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19129,7 +21023,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: userId, teamId, invited, joined, confirm", + "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", @@ -19173,7 +21067,7 @@ }, "x-appwrite": { "method": "createMembership", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -19189,9 +21083,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19292,7 +21183,7 @@ }, "x-appwrite": { "method": "getMembership", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -19308,9 +21199,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/memberships", - "offline-key": "{membershipId}", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19366,7 +21254,7 @@ }, "x-appwrite": { "method": "updateMembership", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -19382,9 +21270,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19456,7 +21341,7 @@ }, "x-appwrite": { "method": "deleteMembership", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -19472,9 +21357,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19532,7 +21414,7 @@ }, "x-appwrite": { "method": "updateMembershipStatus", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -19547,9 +21429,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19631,7 +21510,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -19646,9 +21525,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19695,7 +21571,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -19710,9 +21586,6 @@ "server" ], "packaging": false, - "offline-model": "\/teams\/{teamId}\/prefs", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Session": [] @@ -19779,7 +21652,7 @@ }, "x-appwrite": { "method": "list", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -19793,9 +21666,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19854,7 +21724,7 @@ }, "x-appwrite": { "method": "create", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -19868,9 +21738,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -19952,7 +21819,7 @@ }, "x-appwrite": { "method": "createArgon2User", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -19966,9 +21833,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20046,7 +21910,7 @@ }, "x-appwrite": { "method": "createBcryptUser", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -20060,9 +21924,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20140,7 +22001,7 @@ }, "x-appwrite": { "method": "listIdentities", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -20154,9 +22015,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20212,7 +22070,7 @@ }, "x-appwrite": { "method": "deleteIdentity", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -20226,9 +22084,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20276,7 +22131,7 @@ }, "x-appwrite": { "method": "createMD5User", - "weight": 234, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -20290,9 +22145,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20370,7 +22222,7 @@ }, "x-appwrite": { "method": "createPHPassUser", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -20384,9 +22236,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20464,7 +22313,7 @@ }, "x-appwrite": { "method": "createScryptUser", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -20478,9 +22327,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20593,7 +22439,7 @@ }, "x-appwrite": { "method": "createScryptModifiedUser", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -20607,9 +22453,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20708,7 +22551,7 @@ }, "x-appwrite": { "method": "createSHAUser", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -20722,9 +22565,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20823,7 +22663,7 @@ }, "x-appwrite": { "method": "get", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -20837,9 +22677,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20880,7 +22717,7 @@ }, "x-appwrite": { "method": "delete", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -20894,9 +22731,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -20944,7 +22778,7 @@ }, "x-appwrite": { "method": "updateEmail", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -20958,9 +22792,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21026,7 +22857,7 @@ }, "x-appwrite": { "method": "createJWT", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -21040,9 +22871,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21111,7 +22939,7 @@ }, "x-appwrite": { "method": "updateLabels", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -21125,9 +22953,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21196,7 +23021,7 @@ }, "x-appwrite": { "method": "listLogs", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -21210,9 +23035,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21272,7 +23094,7 @@ }, "x-appwrite": { "method": "listMemberships", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -21286,9 +23108,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21308,6 +23127,27 @@ "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" } ] } @@ -21336,7 +23176,7 @@ }, "x-appwrite": { "method": "updateMfa", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -21350,9 +23190,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21401,24 +23238,19 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], "description": "Delete an authenticator app.", "responses": { - "200": { - "description": "User", - "schema": { - "$ref": "#\/definitions\/user" - } + "204": { + "description": "No content" } }, "x-appwrite": { "method": "deleteMfaAuthenticator", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -21432,9 +23264,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21495,7 +23324,7 @@ }, "x-appwrite": { "method": "listMfaFactors", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -21509,9 +23338,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21559,7 +23385,7 @@ }, "x-appwrite": { "method": "getMfaRecoveryCodes", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -21573,9 +23399,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21621,7 +23444,7 @@ }, "x-appwrite": { "method": "updateMfaRecoveryCodes", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -21635,9 +23458,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21683,7 +23503,7 @@ }, "x-appwrite": { "method": "createMfaRecoveryCodes", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -21697,9 +23517,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21747,7 +23564,7 @@ }, "x-appwrite": { "method": "updateName", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -21761,9 +23578,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21829,7 +23643,7 @@ }, "x-appwrite": { "method": "updatePassword", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -21843,9 +23657,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21911,7 +23722,7 @@ }, "x-appwrite": { "method": "updatePhone", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -21925,9 +23736,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -21993,7 +23801,7 @@ }, "x-appwrite": { "method": "getPrefs", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -22007,9 +23815,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22055,7 +23860,7 @@ }, "x-appwrite": { "method": "updatePrefs", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -22069,9 +23874,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22137,7 +23939,7 @@ }, "x-appwrite": { "method": "listSessions", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -22151,9 +23953,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22199,7 +23998,7 @@ }, "x-appwrite": { "method": "createSession", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -22213,9 +24012,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22256,7 +24052,7 @@ }, "x-appwrite": { "method": "deleteSessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -22270,9 +24066,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22315,7 +24108,7 @@ }, "x-appwrite": { "method": "deleteSession", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -22329,9 +24122,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22387,7 +24177,7 @@ }, "x-appwrite": { "method": "updateStatus", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -22401,9 +24191,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22469,7 +24256,7 @@ }, "x-appwrite": { "method": "listTargets", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -22484,9 +24271,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22544,7 +24328,7 @@ }, "x-appwrite": { "method": "createTarget", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -22559,9 +24343,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22660,7 +24441,7 @@ }, "x-appwrite": { "method": "getTarget", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -22675,9 +24456,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22731,7 +24509,7 @@ }, "x-appwrite": { "method": "updateTarget", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -22746,9 +24524,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22812,9 +24587,7 @@ "consumes": [ "application\/json" ], - "produces": [ - "application\/json" - ], + "produces": [], "tags": [ "users" ], @@ -22826,7 +24599,7 @@ }, "x-appwrite": { "method": "deleteTarget", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -22841,9 +24614,6 @@ "console" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22899,7 +24669,7 @@ }, "x-appwrite": { "method": "createToken", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -22913,9 +24683,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -22984,7 +24751,7 @@ }, "x-appwrite": { "method": "updateEmailVerification", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -22998,9 +24765,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -23066,7 +24830,7 @@ }, "x-appwrite": { "method": "updatePhoneVerification", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -23080,9 +24844,6 @@ "server" ], "packaging": false, - "offline-model": "", - "offline-key": "", - "offline-response-key": "$id", "auth": { "Project": [], "Key": [] @@ -23178,6 +24939,11 @@ "description": "The Users service allows you to manage your project users.", "x-globalAttributes": [] }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications.", + "x-globalAttributes": [] + }, { "name": "functions", "description": "The Functions Service allows you view, create and manage your Cloud Functions.", @@ -23515,6 +25281,31 @@ "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", @@ -23540,6 +25331,31 @@ "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", @@ -26149,6 +27965,193 @@ "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", @@ -26193,19 +28196,39 @@ }, "logging": { "type": "boolean", - "description": "Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", "x-example": false }, "runtime": { "type": "string", - "description": "Function execution runtime.", + "description": "Function execution and build runtime.", "x-example": "python-3.8" }, - "deployment": { + "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.", @@ -26233,7 +28256,7 @@ }, "schedule": { "type": "string", - "description": "Function execution schedult in CRON format.", + "description": "Function execution schedule in CRON format.", "x-example": "5 4 * * *" }, "timeout": { @@ -26298,7 +28321,11 @@ "live", "logging", "runtime", - "deployment", + "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", "scopes", "vars", "events", @@ -26374,6 +28401,100 @@ "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", @@ -26413,7 +28534,7 @@ "description": "The entrypoint file to use to execute the deployment code.", "x-example": "index.js" }, - "size": { + "sourceSize": { "type": "integer", "description": "The code size in bytes.", "x-example": 128, @@ -26425,6 +28546,12 @@ "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.", @@ -26435,9 +28562,19 @@ "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 \"processing\", \"building\", \"waiting\", \"ready\", and \"failed\".", + "description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", "x-example": "ready" }, "buildLogs": { @@ -26445,7 +28582,7 @@ "description": "The build logs.", "x-example": "Compiling source files..." }, - "buildTime": { + "buildDuration": { "type": "integer", "description": "The current build time in seconds.", "x-example": 128, @@ -26510,13 +28647,16 @@ "resourceId", "resourceType", "entrypoint", - "size", + "sourceSize", "buildSize", + "totalSize", "buildId", "activate", + "screenshotLight", + "screenshotDark", "status", "buildLogs", - "buildTime", + "buildDuration", "providerRepositoryName", "providerRepositoryOwner", "providerRepositoryUrl", @@ -26632,7 +28772,7 @@ }, "duration": { "type": "number", - "description": "Function execution duration in seconds.", + "description": "Resource(function\/site) execution duration in seconds.", "x-example": 0.4, "format": "double" }, @@ -26662,70 +28802,6 @@ "duration" ] }, - "build": { - "description": "Build", - "type": "object", - "properties": { - "$id": { - "type": "string", - "description": "Build ID.", - "x-example": "5e5ea5c16897e" - }, - "deploymentId": { - "type": "string", - "description": "The deployment that created this build.", - "x-example": "5e5ea5c16897e" - }, - "status": { - "type": "string", - "description": "The build status. There are a few different types and each one means something different. \\nFailed - The deployment build has failed. More details can usually be found in buildStderr\\nReady - The deployment build was successful and the deployment is ready to be deployed\\nProcessing - The deployment is currently waiting to have a build triggered\\nBuilding - The deployment is currently being built", - "x-example": "ready" - }, - "stdout": { - "type": "string", - "description": "The stdout of the build.", - "x-example": "" - }, - "stderr": { - "type": "string", - "description": "The stderr of the build.", - "x-example": "" - }, - "startTime": { - "type": "string", - "description": "The deployment creation date in ISO 8601 format.", - "x-example": "2020-10-15T06:38:00.000+00:00" - }, - "endTime": { - "type": "string", - "description": "The time the build was finished in ISO 8601 format.", - "x-example": "2020-10-15T06:38:00.000+00:00" - }, - "duration": { - "type": "integer", - "description": "The build duration in seconds.", - "x-example": 0, - "format": "int32" - }, - "size": { - "type": "integer", - "description": "The code size in bytes.", - "x-example": 128, - "format": "int32" - } - }, - "required": [ - "$id", - "deploymentId", - "status", - "stdout", - "stderr", - "startTime", - "endTime", - "duration", - "size" - ] - }, "variable": { "description": "Variable", "type": "object", @@ -26755,6 +28831,11 @@ "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\"", @@ -26772,6 +28853,7 @@ "$updatedAt", "key", "value", + "secret", "resourceType", "resourceId" ] diff --git a/app/config/storage/inputs.php b/app/config/storage/inputs.php index 3b83269261..713801cd7c 100644 --- a/app/config/storage/inputs.php +++ b/app/config/storage/inputs.php @@ -1,8 +1,11 @@ <?php -return [ // Accepted inputs files - 'jpg' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'gif' => 'image/gif', - 'png' => 'image/png', +return [ + // Accepted inputs files + "jpg" => "image/jpeg", + "jpeg" => "image/jpeg", + "gif" => "image/gif", + "png" => "image/png", + "heic" => "image/heic", + "webp" => "image/webp", ]; diff --git a/app/config/storage/mimes.php b/app/config/storage/mimes.php index 26aaf8e1ff..5c1752ca51 100644 --- a/app/config/storage/mimes.php +++ b/app/config/storage/mimes.php @@ -1,70 +1,71 @@ <?php return [ - 'image/jpeg', - 'image/jpeg', - 'image/gif', - 'image/png', - 'image/webp', - // 'image/heic', - 'image/avif', + "image/jpeg", + "image/jpeg", + "image/gif", + "image/png", + "image/webp", + "image/heic", + "image/heic-sequence", + "image/avif", // Video Files - 'video/mp4', - 'video/x-flv', - 'video/webm', - 'application/x-mpegURL', - 'video/MP2T', - 'video/3gpp', - 'video/quicktime', - 'video/x-msvideo', - 'video/x-ms-wmv', + "video/mp4", + "video/x-flv", + "video/webm", + "application/x-mpegURL", + "video/MP2T", + "video/3gpp", + "video/quicktime", + "video/x-msvideo", + "video/x-ms-wmv", // Audio Files - 'audio/basic', // au snd RFC 2046 - 'auido/L24', // Linear PCM RFC 3190 - 'audio/mid', // mid rmi - 'audio/mpeg', // mp3 RFC 3003 - 'audio/mp4', // mp4 audio - 'audio/x-aiff', // aif aifc aiff - 'audio/x-mpegurl', // m3u - 'audio/vnd.rn-realaudio', // ra ram - 'audio/ogg', // Ogg Vorbis RFC 5334 - 'audio/vorbis', // Vorbis RFC 5215 - 'audio/vnd.wav', // wav RFC 2361 - 'audio/x-wav', // php reads .wav as this - https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types - 'audio/aac', //AAC audio - 'audio/x-hx-aac-adts', // AAC audio + "audio/basic", // au snd RFC 2046 + "auido/L24", // Linear PCM RFC 3190 + "audio/mid", // mid rmi + "audio/mpeg", // mp3 RFC 3003 + "audio/mp4", // mp4 audio + "audio/x-aiff", // aif aifc aiff + "audio/x-mpegurl", // m3u + "audio/vnd.rn-realaudio", // ra ram + "audio/ogg", // Ogg Vorbis RFC 5334 + "audio/vorbis", // Vorbis RFC 5215 + "audio/vnd.wav", // wav RFC 2361 + "audio/x-wav", // php reads .wav as this - https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types + "audio/aac", //AAC audio + "audio/x-hx-aac-adts", // AAC audio // Microsoft Word - 'application/msword', - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', - 'application/vnd.ms-word.document.macroEnabled.12', + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.openxmlformats-officedocument.wordprocessingml.template", + "application/vnd.ms-word.document.macroEnabled.12", // Microsoft Excel - 'application/vnd.ms-excel', - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', - 'application/vnd.ms-excel.sheet.macroEnabled.12', - 'application/vnd.ms-excel.template.macroEnabled.12', - 'application/vnd.ms-excel.addin.macroEnabled.12', - 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + "application/vnd.ms-excel", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "application/vnd.openxmlformats-officedocument.spreadsheetml.template", + "application/vnd.ms-excel.sheet.macroEnabled.12", + "application/vnd.ms-excel.template.macroEnabled.12", + "application/vnd.ms-excel.addin.macroEnabled.12", + "application/vnd.ms-excel.sheet.binary.macroEnabled.12", // Microsoft Power Point - 'application/vnd.ms-powerpoint', - 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'application/vnd.openxmlformats-officedocument.presentationml.template', - 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', - 'application/vnd.ms-powerpoint.addin.macroEnabled.12', - 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', - 'application/vnd.ms-powerpoint.template.macroEnabled.12', - 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', + "application/vnd.ms-powerpoint", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "application/vnd.openxmlformats-officedocument.presentationml.template", + "application/vnd.openxmlformats-officedocument.presentationml.slideshow", + "application/vnd.ms-powerpoint.addin.macroEnabled.12", + "application/vnd.ms-powerpoint.presentation.macroEnabled.12", + "application/vnd.ms-powerpoint.template.macroEnabled.12", + "application/vnd.ms-powerpoint.slideshow.macroEnabled.12", // Microsoft Access - 'application/vnd.ms-access', + "application/vnd.ms-access", // Adobe PDF - 'application/pdf', + "application/pdf", ]; diff --git a/app/config/storage/outputs.php b/app/config/storage/outputs.php index cde2a9f38a..49548dda50 100644 --- a/app/config/storage/outputs.php +++ b/app/config/storage/outputs.php @@ -1,12 +1,12 @@ <?php -return [ // Accepted outputs files - 'jpg' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'gif' => 'image/gif', - 'png' => 'image/png', - 'webp' => 'image/webp', - // 'heic' => 'image/heic', - // 'heics' => 'image/heic', - 'avif' => 'image/avif' +return [ + // Accepted outputs files + "jpg" => "image/jpeg", + "jpeg" => "image/jpeg", + "gif" => "image/gif", + "png" => "image/png", + "webp" => "image/webp", + "heic" => "image/heic", + "avif" => "image/avif", ]; diff --git a/app/config/template-runtimes.php b/app/config/template-runtimes.php new file mode 100644 index 0000000000..8f1c0198c2 --- /dev/null +++ b/app/config/template-runtimes.php @@ -0,0 +1,43 @@ +<?php + +// TODO: Remove, replace with runtimes.php directly +// Used in function templates and site frameworks + +return [ + 'NODE' => [ + 'name' => 'node', + 'versions' => ['22', '21.0', '20.0', '19.0', '18.0', '16.0', '14.5'] + ], + 'PYTHON' => [ + 'name' => 'python', + 'versions' => ['3.12', '3.11', '3.10', '3.9', '3.8'] + ], + 'DART' => [ + 'name' => 'dart', + 'versions' => ['3.5', '3.3', '3.1', '3.0', '2.19', '2.18', '2.17', '2.16'] + ], + 'GO' => [ + 'name' => 'go', + 'versions' => ['1.23'] + ], + 'PHP' => [ + 'name' => 'php', + 'versions' => ['8.3', '8.2', '8.1', '8.0'] + ], + 'DENO' => [ + 'name' => 'deno', + 'versions' => ['2.0', '1.46', '1.40', '1.35', '1.24', '1.21'] + ], + 'BUN' => [ + 'name' => 'bun', + 'versions' => ['1.1', '1.0'] + ], + 'RUBY' => [ + 'name' => 'ruby', + 'versions' => ['3.3', '3.2', '3.1', '3.0'] + ], + 'FLUTTER' => [ + 'name' => 'flutter', + 'versions' => ['3.24'] + ], +]; diff --git a/app/config/function-templates.php b/app/config/templates/function.php similarity index 95% rename from app/config/function-templates.php rename to app/config/templates/function.php index 762c33dd9a..d8426ad900 100644 --- a/app/config/function-templates.php +++ b/app/config/templates/function.php @@ -1,39 +1,8 @@ <?php -const TEMPLATE_RUNTIMES = [ - 'NODE' => [ - 'name' => 'node', - 'versions' => ['22', '21.0', '20.0', '19.0', '18.0', '16.0', '14.5'] - ], - 'PYTHON' => [ - 'name' => 'python', - 'versions' => ['3.12', '3.11', '3.10', '3.9', '3.8'] - ], - 'DART' => [ - 'name' => 'dart', - 'versions' => ['3.5', '3.3', '3.1', '3.0', '2.19', '2.18', '2.17', '2.16', '2.16'] - ], - 'GO' => [ - 'name' => 'go', - 'versions' => ['1.23'] - ], - 'PHP' => [ - 'name' => 'php', - 'versions' => ['8.3', '8.2', '8.1', '8.0'] - ], - 'DENO' => [ - 'name' => 'deno', - 'versions' => ['2.0', '1.46', '1.40', '1.35', '1.24', '1.21'] - ], - 'BUN' => [ - 'name' => 'bun', - 'versions' => ['1.1', '1.0'] - ], - 'RUBY' => [ - 'name' => 'ruby', - 'versions' => ['3.3', '3.2', '3.1', '3.0'] - ], -]; +use Utopia\Config\Config; + +$templateRuntimes = Config::getParam('template-runtimes'); function getRuntimes($runtime, $commands, $entrypoint, $providerRootDirectory, $versionsDenyList = []) { @@ -54,6 +23,7 @@ return [ 'icon' => 'icon-lightning-bolt', 'id' => 'starter', 'name' => 'Starter function', + 'score' => 5, 'tagline' => 'A simple function to get started. Edit this function to explore endless possibilities with Appwrite Functions.', 'permissions' => ['any'], @@ -62,24 +32,24 @@ return [ 'timeout' => 15, 'useCases' => ['starter'], 'runtimes' => [ - ...getRuntimes(TEMPLATE_RUNTIMES['NODE'], 'npm install', 'src/main.js', 'node/starter'), + ...getRuntimes($templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/starter'), ...getRuntimes( - TEMPLATE_RUNTIMES['PYTHON'], + $templateRuntimes['PYTHON'], 'pip install -r requirements.txt', 'src/main.py', 'python/starter' ), - ...getRuntimes(TEMPLATE_RUNTIMES['DART'], 'dart pub get', 'lib/main.dart', 'dart/starter'), - ...getRuntimes(TEMPLATE_RUNTIMES['GO'], '', 'main.go', 'go/starter'), + ...getRuntimes($templateRuntimes['DART'], 'dart pub get', 'lib/main.dart', 'dart/starter'), + ...getRuntimes($templateRuntimes['GO'], '', 'main.go', 'go/starter'), ...getRuntimes( - TEMPLATE_RUNTIMES['PHP'], + $templateRuntimes['PHP'], 'composer install', 'src/index.php', 'php/starter' ), - ...getRuntimes(TEMPLATE_RUNTIMES['DENO'], 'deno cache src/main.ts', 'src/main.ts', 'deno/starter'), - ...getRuntimes(TEMPLATE_RUNTIMES['BUN'], 'bun install', 'src/main.ts', 'bun/starter'), - ...getRuntimes(TEMPLATE_RUNTIMES['RUBY'], 'bundle install', 'lib/main.rb', 'ruby/starter'), + ...getRuntimes($templateRuntimes['DENO'], 'deno cache src/main.ts', 'src/main.ts', 'deno/starter'), + ...getRuntimes($templateRuntimes['BUN'], 'bun install', 'src/main.ts', 'bun/starter'), + ...getRuntimes($templateRuntimes['RUBY'], 'bundle install', 'lib/main.rb', 'ruby/starter'), ], 'instructions' => 'For documentation and instructions check out <a target="_blank" rel="noopener noreferrer" class="link" href="https://github.com/appwrite/templates/tree/main/node/starter">file</a>.', 'vcsProvider' => 'github', @@ -93,6 +63,7 @@ return [ 'icon' => 'icon-upstash', 'id' => 'query-upstash-vector', 'name' => 'Query Upstash Vector', + 'score' => 4, 'tagline' => 'Vector database that stores text embeddings and context retrieval for LLMs', 'permissions' => ['any'], 'events' => [], @@ -101,7 +72,7 @@ return [ 'useCases' => ['databases'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/query-upstash-vector' @@ -137,6 +108,7 @@ return [ 'icon' => 'icon-redis', 'id' => 'query-redis-labs', 'name' => 'Query Redis Labs', + 'score' => 4, 'tagline' => 'Key-value database with advanced caching capabilities.', 'permissions' => ['any'], 'events' => [], @@ -145,7 +117,7 @@ return [ 'useCases' => ['databases'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/query-redis-labs' @@ -180,6 +152,7 @@ return [ 'icon' => 'icon-neo4j', 'id' => 'query-neo4j-auradb', 'name' => 'Query Neo4j AuraDB', + 'score' => 4, 'tagline' => 'Graph database with focus on relations between data.', 'permissions' => ['any'], 'events' => [], @@ -188,7 +161,7 @@ return [ 'useCases' => ['databases'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/query-neo4j-auradb' @@ -231,6 +204,7 @@ return [ 'icon' => 'icon-mongodb', 'id' => 'query-mongo-atlas', 'name' => 'Query MongoDB Atlas', + 'score' => 4, 'tagline' => 'Realtime NoSQL document database with geospecial, graph, search, and vector suport.', 'permissions' => ['any'], @@ -240,7 +214,7 @@ return [ 'useCases' => ['databases'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/query-mongo-atlas' @@ -268,6 +242,7 @@ return [ 'icon' => 'icon-neon', 'id' => 'query-neon-postgres', 'name' => 'Query Neon Postgres', + 'score' => 4, 'tagline' => 'Reliable SQL database with replication, point-in-time recovery, and pgvector support.', 'permissions' => ['any'], @@ -277,7 +252,7 @@ return [ 'useCases' => ['databases'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/query-neon-postgres' @@ -336,6 +311,7 @@ return [ 'icon' => 'icon-open-ai', 'id' => 'prompt-chatgpt', 'name' => 'Prompt ChatGPT', + 'score' => 7, 'tagline' => 'Ask questions and let OpenAI GPT-3.5-turbo answer.', 'permissions' => ['any'], 'events' => [], @@ -344,25 +320,25 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/prompt-chatgpt' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PYTHON'], + $templateRuntimes['PYTHON'], 'pip install -r requirements.txt', 'src/main.py', 'python/prompt_chatgpt' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PHP'], + $templateRuntimes['PHP'], 'composer install', 'src/index.php', 'php/prompt-chatgpt' ), ...getRuntimes( - TEMPLATE_RUNTIMES['DART'], + $templateRuntimes['DART'], 'dart pub get', 'lib/main.dart', 'dart/prompt_chatgpt' @@ -397,6 +373,7 @@ return [ 'icon' => 'icon-discord', 'id' => 'discord-command-bot', 'name' => 'Discord Command Bot', + 'score' => 6, 'tagline' => 'Simple command using Discord Interactions.', 'permissions' => ['any'], 'events' => [], @@ -405,19 +382,19 @@ return [ 'useCases' => ['messaging'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install && npm run setup', 'src/main.js', 'node/discord-command-bot' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PYTHON'], + $templateRuntimes['PYTHON'], 'pip install -r requirements.txt && python src/setup.py', 'src/main.py', 'python/discord_command_bot' ), ...getRuntimes( - TEMPLATE_RUNTIMES['GO'], + $templateRuntimes['GO'], '', 'main.go', 'go/discord-command-bot' @@ -460,6 +437,7 @@ return [ 'icon' => 'icon-perspective-api', 'id' => 'analyze-with-perspectiveapi', 'name' => 'Analyze with PerspectiveAPI', + 'score' => 5, 'tagline' => 'Automate moderation by getting toxicity of messages.', 'permissions' => ['any'], 'events' => [], @@ -468,7 +446,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/analyze-with-perspectiveapi' @@ -495,6 +473,7 @@ return [ 'icon' => 'icon-pangea', 'id' => 'censor-with-redact', 'name' => 'Censor with Redact', + 'score' => 5, 'tagline' => 'Censor sensitive information from a provided text string using Redact API by Pangea.', 'permissions' => ['any'], @@ -504,19 +483,19 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/censor-with-redact' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PYTHON'], + $templateRuntimes['PYTHON'], 'pip install -r requirements.txt', 'src/main.py', 'python/censor_with_redact' ), ...getRuntimes( - TEMPLATE_RUNTIMES['DART'], + $templateRuntimes['DART'], 'dart pub get', 'lib/main.dart', 'dart/censor_with_redact' @@ -543,6 +522,7 @@ return [ 'icon' => 'icon-document', 'id' => 'generate-pdf', 'name' => 'Generate PDF', + 'score' => 7, 'tagline' => 'Document containing sample invoice in PDF format.', 'permissions' => ['any'], 'events' => [], @@ -550,7 +530,7 @@ return [ 'timeout' => 15, 'useCases' => ['utilities'], 'runtimes' => [ - ...getRuntimes(TEMPLATE_RUNTIMES['NODE'], 'npm install', 'src/main.js', 'node/generate-pdf') + ...getRuntimes($templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/generate-pdf') ], 'instructions' => 'For documentation and instructions check out <a target="_blank" rel="noopener noreferrer" class="link" href="https://github.com/appwrite/templates/tree/main/node/generate-pdf">file</a>.', 'vcsProvider' => 'github', @@ -564,6 +544,7 @@ return [ 'icon' => 'icon-github', 'id' => 'github-issue-bot', 'name' => 'GitHub issue bot', + 'score' => 4, 'tagline' => 'Automate the process of responding to newly opened issues in a GitHub repository.', 'permissions' => ['any'], @@ -573,7 +554,7 @@ return [ 'useCases' => ['dev-tools'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/github-issue-bot' @@ -608,6 +589,7 @@ return [ 'icon' => 'icon-bookmark', 'id' => 'url-shortener', 'name' => 'URL shortener', + 'score' => 3, 'tagline' => 'Generate URL with short ID and redirect to the original URL when visited.', 'permissions' => ['any'], 'events' => [], @@ -616,7 +598,7 @@ return [ 'useCases' => ['utilities'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/url-shortener' @@ -659,6 +641,7 @@ return [ 'icon' => 'icon-algolia', 'id' => 'sync-with-algolia', 'name' => 'Sync with Algolia', + 'score' => 4, 'tagline' => 'Intuitive search bar for any data in Appwrite Databases.', 'permissions' => ['any'], 'events' => [], @@ -667,19 +650,19 @@ return [ 'useCases' => ['databases'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/sync-with-algolia' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PYTHON'], + $templateRuntimes['PYTHON'], 'pip install -r requirements.txt', 'src/main.py', 'python/sync_with_algolia' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PHP'], + $templateRuntimes['PHP'], 'composer install', 'src/index.php', 'php/sync-with-algolia' @@ -740,6 +723,7 @@ return [ 'icon' => 'icon-meilisearch', 'id' => 'sync-with-meilisearch', 'name' => 'Sync with Meilisearch', + 'score' => 4, 'tagline' => 'Intuitive search bar for any data in Appwrite Databases.', 'permissions' => ['any'], 'events' => [], @@ -748,31 +732,31 @@ return [ 'useCases' => ['databases'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/sync-with-meilisearch' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PYTHON'], + $templateRuntimes['PYTHON'], 'pip install -r requirements.txt', 'src/main.py', 'python/sync-with-meilisearch' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PHP'], + $templateRuntimes['PHP'], 'composer install', 'src/index.php', 'php/sync-with-meilisearch' ), ...getRuntimes( - TEMPLATE_RUNTIMES['BUN'], + $templateRuntimes['BUN'], 'bun install', 'src/main.ts', 'bun/sync-with-meilisearch' ), ...getRuntimes( - TEMPLATE_RUNTIMES['RUBY'], + $templateRuntimes['RUBY'], 'bundle install', 'lib/main.rb', 'ruby/sync-with-meilisearch' @@ -833,6 +817,7 @@ return [ 'icon' => 'icon-vonage', 'id' => 'whatsapp-with-vonage', 'name' => 'WhatsApp with Vonage', + 'score' => 6, 'tagline' => 'Simple bot to answer WhatsApp messages.', 'permissions' => ['any'], 'events' => [], @@ -841,37 +826,37 @@ return [ 'useCases' => ['messaging'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/whatsapp-with-vonage' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PYTHON'], + $templateRuntimes['PYTHON'], 'pip install -r requirements.txt', 'src/main.py', 'python/whatsapp_with_vonage' ), ...getRuntimes( - TEMPLATE_RUNTIMES['DART'], + $templateRuntimes['DART'], 'dart pub get', 'lib/main.dart', 'dart/whatsapp-with-vonage' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PHP'], + $templateRuntimes['PHP'], 'composer install', 'src/index.php', 'php/whatsapp-with-vonage' ), ...getRuntimes( - TEMPLATE_RUNTIMES['BUN'], + $templateRuntimes['BUN'], 'bun install', 'src/main.ts', 'bun/whatsapp-with-vonage' ), ...getRuntimes( - TEMPLATE_RUNTIMES['RUBY'], + $templateRuntimes['RUBY'], 'bundle install', 'lib/main.rb', 'ruby/whatsapp-with-vonage' @@ -919,6 +904,7 @@ return [ 'icon' => 'icon-bell', 'id' => 'push-notification-with-fcm', 'name' => 'Push notification with FCM', + 'score' => 4, 'tagline' => 'Send push notifications to your users using Firebase Cloud Messaging (FCM).', 'permissions' => ['any'], 'events' => [], @@ -927,7 +913,7 @@ return [ 'useCases' => ['messaging'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/push-notification-with-fcm' @@ -975,6 +961,7 @@ return [ 'icon' => 'icon-mail', 'id' => 'email-contact-form', 'name' => 'Email contact form', + 'score' => 7, 'tagline' => 'Sends an email with the contents of a HTML form.', 'permissions' => ['any'], 'events' => [], @@ -983,19 +970,19 @@ return [ 'useCases' => ['utilities'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/email-contact-form' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PYTHON'], + $templateRuntimes['PYTHON'], 'pip install -r requirements.txt', 'src/main.py', 'python/email_contact_form' ), ...getRuntimes( - TEMPLATE_RUNTIMES['PHP'], + $templateRuntimes['PHP'], 'composer install', 'src/index.php', 'php/email-contact-form' @@ -1058,6 +1045,7 @@ return [ 'icon' => 'icon-stripe', 'id' => 'subscriptions-with-stripe', 'name' => 'Subscriptions with Stripe', + 'score' => 6, 'tagline' => 'Receive recurring card payments and grant subscribers extra permissions.', 'permissions' => ['any'], 'events' => [], @@ -1066,7 +1054,7 @@ return [ 'useCases' => ['utilities'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/subscriptions-with-stripe' @@ -1099,6 +1087,7 @@ return [ 'icon' => 'icon-stripe', 'id' => 'payments-with-stripe', 'name' => 'Payments with Stripe', + 'score' => 8, 'tagline' => 'Receive card payments and store paid orders.', 'permissions' => ['any'], 'events' => [], @@ -1107,7 +1096,7 @@ return [ 'useCases' => ['utilities'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/payments-with-stripe' @@ -1156,6 +1145,7 @@ return [ 'icon' => 'icon-chat', 'id' => 'text-generation-with-huggingface', 'name' => 'Text generation', + 'score' => 5, 'tagline' => 'Generate text using the Hugging Face inference API.', 'permissions' => ['any'], 'events' => [], @@ -1164,7 +1154,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/text-generation-with-huggingface' @@ -1190,6 +1180,7 @@ return [ 'icon' => 'icon-translate', 'id' => 'language-translation-with-huggingface', 'name' => 'Language translation', + 'score' => 5, 'tagline' => 'Translate text using the Hugging Face inference API.', 'permissions' => ['any'], 'events' => [], @@ -1198,7 +1189,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/language-translation-with-huggingface' @@ -1224,6 +1215,7 @@ return [ 'icon' => 'icon-eye', 'id' => 'image-classification-with-huggingface', 'name' => 'Image classification', + 'score' => 5, 'tagline' => 'Classify images using the Hugging Face inference API.', 'permissions' => ['any'], 'events' => ['buckets.*.files.*.create'], @@ -1232,7 +1224,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install && npm run setup', 'src/main.js', 'node/image-classification-with-huggingface' @@ -1282,6 +1274,7 @@ return [ 'icon' => 'icon-eye', 'id' => 'object-detection-with-huggingface', 'name' => 'Object detection', + 'score' => 5, 'tagline' => 'Detect objects in images using the Hugging Face inference API.', 'permissions' => ['any'], 'events' => ['buckets.*.files.*.create'], @@ -1290,7 +1283,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install && npm run setup', 'src/main.js', 'node/object-detection-with-huggingface' @@ -1340,6 +1333,7 @@ return [ 'icon' => 'icon-text', 'id' => 'speech-recognition-with-huggingface', 'name' => 'Speech recognition', + 'score' => 5, 'tagline' => 'Transcribe audio to text using the Hugging Face inference API.', 'permissions' => ['any'], 'events' => ['buckets.*.files.*.create'], @@ -1348,7 +1342,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install && npm run setup', 'src/main.js', 'node/speech-recognition-with-huggingface' @@ -1398,6 +1392,7 @@ return [ 'icon' => 'icon-chat', 'id' => 'text-to-speech-with-huggingface', 'name' => 'Text to speech', + 'score' => 5, 'tagline' => 'Convert text to speech using the Hugging Face inference API.', 'permissions' => ['any'], 'events' => ['databases.*.collections.*.documents.*.create'], @@ -1406,7 +1401,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install && npm run setup', 'src/main.js', 'node/text-to-speech-with-huggingface' @@ -1456,6 +1451,7 @@ return [ 'icon' => 'icon-chip', 'id' => 'generate-with-replicate', 'name' => 'Generate with Replicate', + 'score' => 5, 'tagline' => "Generate text, audio and images using Replicate's API.", 'permissions' => ['any'], 'events' => [], @@ -1464,7 +1460,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/generate-with-replicate' @@ -1491,6 +1487,7 @@ return [ 'icon' => 'icon-chip', 'id' => 'generate-with-together-ai', 'name' => 'Generate with Together AI', + 'score' => 5, 'tagline' => "Generate text and images using Together AI's API.", 'permissions' => ['any'], 'events' => [], @@ -1499,7 +1496,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/generate-with-together-ai' @@ -1533,6 +1530,7 @@ return [ 'icon' => 'icon-chip', 'id' => 'chat-with-perplexity-ai', 'name' => 'Chat with Perplexity AI', + 'score' => 5, 'tagline' => 'Create a chatbot using the Perplexity AI API.', 'permissions' => ['any'], 'events' => [], @@ -1541,7 +1539,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/chat-with-perplexity-ai' @@ -1567,12 +1565,14 @@ return [ 'required' => false, 'type' => 'number' ] - ] + ], + 'scopes' => [] ], [ 'icon' => 'icon-chip', 'id' => 'generate-with-replicate', 'name' => 'Generate with Replicate', + 'score' => 5, 'tagline' => "Generate text, audio and images using Replicate's API.", 'permissions' => ['any'], 'events' => [], @@ -1581,7 +1581,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/generate-with-replicate' @@ -1608,6 +1608,7 @@ return [ 'icon' => 'icon-document-search', 'id' => 'sync-with-pinecone', 'name' => 'Sync with Pinecone', + 'score' => 4, 'tagline' => "Sync your Appwrite database with Pinecone's vector database.", 'permissions' => ['any'], 'events' => [], @@ -1616,7 +1617,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/sync-with-pinecone' @@ -1671,6 +1672,7 @@ return [ 'icon' => 'icon-chip', 'id' => 'rag-with-langchain', 'name' => 'RAG with LangChain', + 'score' => 6, 'tagline' => 'Generate text using a LangChain RAG model', 'permissions' => ['any'], 'events' => [], @@ -1679,7 +1681,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/rag-with-langchain' @@ -1734,6 +1736,7 @@ return [ 'icon' => 'icon-chat', 'id' => 'speak-with-elevenlabs', 'name' => 'Speak with ElevenLabs', + 'score' => 5, 'tagline' => 'Convert text to speech using the ElevenLabs API.', 'permissions' => ['any'], 'cron' => '', @@ -1742,7 +1745,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/speak-with-elevenlabs' @@ -1789,6 +1792,7 @@ return [ 'icon' => 'icon-chip', 'id' => 'speak-with-lmnt', 'name' => 'Speak with LMNT', + 'score' => 5, 'tagline' => 'Convert text to speech using the LMNT API.', 'permissions' => ['any'], 'cron' => '', @@ -1797,7 +1801,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/speak-with-lmnt' @@ -1830,6 +1834,7 @@ return [ 'icon' => 'icon-chip', 'id' => 'chat-with-anyscale', 'name' => 'Chat with AnyScale', + 'score' => 5, 'tagline' => 'Create a chatbot using the AnyScale API.', 'permissions' => ['any'], 'cron' => '', @@ -1838,7 +1843,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/chat-with-anyscale' @@ -1871,6 +1876,7 @@ return [ 'icon' => 'icon-music-note', 'id' => 'music-generation-with-huggingface', 'name' => 'Music generation', + 'score' => 4, 'tagline' => 'Generate music from a text prompt using the Hugging Face inference API.', 'permissions' => ['any'], 'events' => [], @@ -1879,7 +1885,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install && npm run setup', 'src/main.js', 'node/music-generation-with-huggingface' @@ -1913,6 +1919,7 @@ return [ 'icon' => 'icon-chip', 'id' => 'generate-with-fal-ai', 'name' => 'Generate with fal.ai', + 'score' => 5, 'tagline' => "Generate images using fal.ai's API.", 'permissions' => ['any'], 'events' => [], @@ -1921,7 +1928,7 @@ return [ 'useCases' => ['ai'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/generate-with-fal-ai' @@ -1948,6 +1955,7 @@ return [ 'icon' => 'icon-currency-dollar', 'id' => 'subscriptions-with-lemon-squeezy', 'name' => 'Subscriptions with Lemon Squeezy', + 'score' => 6, 'tagline' => 'Receive recurring card payments and grant subscribers extra permissions.', 'permissions' => ['any'], 'events' => [], @@ -1956,7 +1964,7 @@ return [ 'useCases' => ['utilities'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/subscriptions-with-lemon-squeezy' @@ -2003,6 +2011,7 @@ return [ 'icon' => 'icon-currency-dollar', 'id' => 'payments-with-lemon-squeezy', 'name' => 'Payments with Lemon Squeezy', + 'score' => 6, 'tagline' => 'Receive card payments and store paid orders.', 'permissions' => ['any'], 'events' => [], @@ -2011,7 +2020,7 @@ return [ 'useCases' => ['utilities'], 'runtimes' => [ ...getRuntimes( - TEMPLATE_RUNTIMES['NODE'], + $templateRuntimes['NODE'], 'npm install', 'src/main.js', 'node/payments-with-lemon-squeezy' diff --git a/app/config/templates/site.php b/app/config/templates/site.php new file mode 100644 index 0000000000..6989cc026d --- /dev/null +++ b/app/config/templates/site.php @@ -0,0 +1,1150 @@ +<?php + +use Utopia\System\System; + +/** + * List of Appwrite Sites templates + */ + +$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; +$hostname = System::getEnv('_APP_DOMAIN'); + +// TODO: Development override +if (System::getEnv('_APP_ENV') === 'development') { + $hostname = 'localhost'; +} + +$url = $protocol . '://' . $hostname; + +class UseCases +{ + public const PORTFOLIO = 'portfolio'; + public const STARTER = 'starter'; + public const EVENTS = 'events'; + public const ECOMMERCE = 'ecommerce'; + public const DOCUMENTATION = 'documentation'; + public const BLOG = 'blog'; +} + +const TEMPLATE_FRAMEWORKS = [ + 'SVELTEKIT' => [ + 'key' => 'sveltekit', + 'name' => 'SvelteKit', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'outputDirectory' => './build', + 'buildRuntime' => 'node-22', + 'adapter' => 'ssr', + 'fallbackFile' => '', + ], + 'NEXTJS' => [ + 'key' => 'nextjs', + 'name' => 'Next.js', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'outputDirectory' => './.next', + 'buildRuntime' => 'node-22', + 'adapter' => 'ssr', + 'fallbackFile' => '', + ], + 'NUXT' => [ + 'key' => 'nuxt', + 'name' => 'Nuxt', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'outputDirectory' => './.output', + 'buildRuntime' => 'node-22', + 'adapter' => 'ssr', + 'fallbackFile' => '', + ], + 'REMIX' => [ + 'key' => 'remix', + 'name' => 'Remix', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'outputDirectory' => './build', + 'buildRuntime' => 'node-22', + 'adapter' => 'ssr', + 'fallbackFile' => '', + ], + 'ASTRO' => [ + 'key' => 'astro', + 'name' => 'Astro', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'outputDirectory' => './dist', + 'buildRuntime' => 'node-22', + 'adapter' => 'ssr', + 'fallbackFile' => '', + ], + 'FLUTTER' => [ + 'key' => 'flutter', + 'name' => 'Flutter', + 'installCommand' => '', + 'buildCommand' => 'flutter build web', + 'outputDirectory' => './build/web', + 'buildRuntime' => 'flutter-3.29', + 'adapter' => 'static', + 'fallbackFile' => '', + ], + 'VITE' => [ + 'key' => 'vite', + 'name' => 'Vite', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'buildRuntime' => 'node-22', + 'adapter' => 'static', + 'outputDirectory' => './dist', + ], + 'REACT' => [ + 'key' => 'react', + 'name' => 'React', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'buildRuntime' => 'node-22', + 'adapter' => 'static', + 'outputDirectory' => './dist', + 'fallbackFile' => 'index.html', + ], + 'ANGULAR' => [ + 'key' => 'angular', + 'name' => 'Angular', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'buildRuntime' => 'node-22', + 'adapter' => 'static', + 'outputDirectory' => './dist/angular/browser', + 'fallbackFile' => 'index.html', + ], + 'ANALOG' => [ + 'key' => 'analog', + 'name' => 'Analog', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'buildRuntime' => 'node-22', + 'adapter' => 'ssr', + 'outputDirectory' => './dist/analog', + ], + 'VUE' => [ + 'key' => 'vue', + 'name' => 'Vue.js', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'buildRuntime' => 'node-22', + 'adapter' => 'static', + 'outputDirectory' => './dist', + 'fallbackFile' => 'index.html', + ], + 'OTHER' => [ + 'key' => 'other', + 'name' => 'Other', + 'installCommand' => '', + 'buildCommand' => '', + 'buildRuntime' => 'node-22', + 'adapter' => 'static', + 'outputDirectory' => './', + ], + 'LYNX' => [ + 'key' => 'lynx', + 'name' => 'Lynx', + 'installCommand' => 'npm install && cd web && npm install && cd ..', + 'buildCommand' => 'npm run build && cd web && npm run build && cd ..', + 'buildRuntime' => 'node-22', + 'adapter' => 'static', + 'outputDirectory' => './web/dist', + 'fallbackFile' => 'index.html', + ], +]; + +function getFramework(string $frameworkEnum, array $overrides) +{ + $settings = \array_merge(TEMPLATE_FRAMEWORKS[$frameworkEnum], $overrides); + return $settings; +} + +return [ + [ + 'key' => 'template-for-documentation', + 'name' => 'Documentation template', + 'tagline' => 'Modern site to store your knowledge with a clean design, full-text search, dark mode, and more.', + 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::DOCUMENTATION], + 'screenshotDark' => $url . '/images/sites/templates/template-for-documentation-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/template-for-documentation-light.png', + 'frameworks' => [ + getFramework('ASTRO', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'template-for-documentation', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [] + ], + [ + 'key' => 'lynx-starter', + 'name' => 'Lynx Starter', + 'tagline' => 'Sample application built with Lynx, a cross-platform framework focused on performance.', + '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/lynx-starter-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/lynx-starter-light.png', + 'frameworks' => [ + getFramework('LYNX', [ + 'providerRootDirectory' => './lynx/starter', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'vitepress', + 'name' => 'Vitepress', + 'tagline' => 'Platform for documentation and knowledge sharing powered by Vite.', + 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::DOCUMENTATION], + 'screenshotDark' => $url . '/images/sites/templates/vitepress-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/vitepress-light.png', + 'frameworks' => [ + getFramework('VITE', [ + 'providerRootDirectory' => './vite/vitepress', + 'outputDirectory' => '404.html', + 'installCommand' => 'npm i vitepress && npm install', + 'buildCommand' => 'npm run docs:build', + 'outputDirectory' => './.vitepress/dist', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'vuepress', + 'name' => 'Vuepress', + 'tagline' => 'Platform for documentation and knowledge sharing powered by Vue.', + 'score' => 4, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::DOCUMENTATION], + 'screenshotDark' => $url . '/images/sites/templates/vuepress-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/vuepress-light.png', + 'frameworks' => [ + getFramework('VUE', [ + 'providerRootDirectory' => './vue/vuepress', + 'outputDirectory' => '404.html', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'outputDirectory' => './src/.vuepress/dist', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'docusaurus', + 'name' => 'Docusaurus', + 'tagline' => 'Platform for documentation and knowledge sharing powered by React.', + 'score' => 4, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::DOCUMENTATION], + 'screenshotDark' => $url . '/images/sites/templates/docusaurus-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/docusaurus-light.png', + 'frameworks' => [ + getFramework('REACT', [ + 'providerRootDirectory' => './react/docusaurus', + 'outputDirectory' => '404.html', + 'installCommand' => 'npm install', + 'buildCommand' => 'npm run build', + 'outputDirectory' => './build', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'nxt-lnk', + 'name' => 'Nxt Lnk', + 'tagline' => 'Personal website for creators to merge all URLs to social profiles.', + 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::PORTFOLIO], + 'screenshotDark' => $url . '/images/sites/templates/nxt-lnk-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/nxt-lnk-light.png', + 'frameworks' => [ + getFramework('NEXTJS', [ + 'providerRootDirectory' => './nextjs/nxtlnk', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'magic-portfolio', + 'name' => 'Magic Portfolio', + 'tagline' => 'Complex personal website to showcase your projects, articles, and more.', + 'score' => 7, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::PORTFOLIO], + 'screenshotDark' => $url . '/images/sites/templates/magic-portfolio-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/magic-portfolio-light.png', + 'frameworks' => [ + getFramework('NEXTJS', [ + 'providerRootDirectory' => './nextjs/magic-portfolio', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'littlelink', + 'name' => 'LittleLink', + 'tagline' => 'Personal website for creators to merge all URLs to social profiles.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::PORTFOLIO], + 'screenshotDark' => $url . '/images/sites/templates/littlelink-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/littlelink-light.png', + 'frameworks' => [ + getFramework('OTHER', [ + 'providerRootDirectory' => './other/littlelink', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'logspot', + 'name' => 'Logspot', + 'tagline' => 'Website to publish changelogs of your application.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::BLOG], + 'screenshotDark' => $url . '/images/sites/templates/logspot-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/logspot-light.png', + 'frameworks' => [ + getFramework('NUXT', [ + 'providerRootDirectory' => './nuxt/logspot', + 'buildCommand' => 'npm run generate', + 'outputDirectory' => './dist', + 'adapter' => 'static', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'astro-nano', + 'name' => 'Astro Nano', + 'tagline' => 'Minimal personal website to showcase your projects, articles, and more.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::PORTFOLIO], + 'screenshotDark' => $url . '/images/sites/templates/astro-nano-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/astro-nano-light.png', + 'frameworks' => [ + getFramework('ASTRO', [ + 'providerRootDirectory' => './astro/nano', + 'outputDirectory' => './dist', + 'adapter' => 'static', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'astro-starlight', + 'name' => 'Astro Starlight', + 'tagline' => 'Platform for documentation and knowledge sharing powered by Astro.', + 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::DOCUMENTATION], + 'screenshotDark' => $url . '/images/sites/templates/astro-starlight-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/astro-starlight-light.png', + 'frameworks' => [ + getFramework('ASTRO', [ + 'providerRootDirectory' => './astro/starlight', + 'outputDirectory' => './dist', + 'adapter' => 'static', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'astro-sphere', + 'name' => 'Astro Sphere', + 'tagline' => 'Modern personal website to showcase your projects, articles, and more.', + 'score' => 7, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::PORTFOLIO], + 'screenshotDark' => $url . '/images/sites/templates/astro-sphere-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/astro-sphere-light.png', + 'frameworks' => [ + getFramework('ASTRO', [ + 'providerRootDirectory' => './astro/sphere', + 'outputDirectory' => './dist', + 'adapter' => 'static', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'astro-starlog', + 'name' => 'Astro Starlog', + 'tagline' => 'Platform for publishing written content and media powered by Astro.', + 'score' => 5, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::BLOG], + 'screenshotDark' => $url . '/images/sites/templates/astro-starlog-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/astro-starlog-light.png', + 'frameworks' => [ + getFramework('ASTRO', [ + 'providerRootDirectory' => './astro/starlog', + 'outputDirectory' => './dist', + 'adapter' => 'static', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'onelink', + 'name' => 'Onelink', + 'tagline' => 'Personal website for creators to merge all URLs to social profiles.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::PORTFOLIO], + 'screenshotDark' => $url . '/images/sites/templates/onelink-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/onelink-light.png', + 'frameworks' => [ + getFramework('NUXT', [ + 'providerRootDirectory' => './nuxt/onelink', + 'buildCommand' => 'npm run generate', + 'outputDirectory' => './dist', + 'adapter' => 'static', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], + [ + 'key' => 'starter-for-flutter', + 'name' => 'Flutter starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple Flutter application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-flutter-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-flutter-light.png', + 'frameworks' => [ + getFramework('FLUTTER', [ + 'providerRootDirectory' => './', + 'buildCommand' => 'bash build.sh', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-flutter', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'APPWRITE_PUBLIC_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-js', + 'name' => 'JavaScript starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple JavaScript application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-js-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-js-light.png', + 'frameworks' => [ + getFramework('VITE', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-js', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'VITE_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'VITE_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'VITE_APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-angular', + 'name' => 'Angular starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple Angular application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-angular-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-angular-light.png', + 'frameworks' => [ + getFramework('ANGULAR', [ + 'providerRootDirectory' => './', + 'outputDirectory' => './dist/angular-starter-kit-for-appwrite/browser', + 'buildCommand' => 'bash prepare-env.sh && npm run build' + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-angular', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-astro', + 'name' => 'Astro starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple Astro application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-astro-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-astro-light.png', + 'frameworks' => [ + getFramework('ASTRO', [ + 'providerRootDirectory' => './', + 'adapter' => 'static', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-astro', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'PUBLIC_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'PUBLIC_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'PUBLIC_APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-analog', + 'name' => 'Analog starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple Analog application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-analog-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-analog-light.png', + 'frameworks' => [ + getFramework('ANALOG', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-analog', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'VITE_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'VITE_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'VITE_APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-remix', + 'name' => 'Remix starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple Remix application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-remix-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-remix-light.png', + 'frameworks' => [ + getFramework('REMIX', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-remix', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'VITE_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'VITE_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'VITE_APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-svelte', + 'name' => 'Svelte starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple Svelte application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-svelte-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-svelte-light.png', + 'frameworks' => [ + getFramework('SVELTEKIT', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-svelte', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'PUBLIC_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'PUBLIC_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'PUBLIC_APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-react', + 'name' => 'React starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple React application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-react-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-react-light.png', + 'frameworks' => [ + getFramework('REACT', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-react', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'VITE_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'VITE_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'VITE_APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-vue', + 'name' => 'Vue starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple Vue application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-vue-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-vue-light.png', + 'frameworks' => [ + getFramework('VUE', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-vue', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'VITE_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'VITE_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'VITE_APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-react-native', + 'name' => 'React Native starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple React Native application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-react-native-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-react-native-light.png', + 'frameworks' => [ + getFramework('REACT', [ + 'providerRootDirectory' => './', + 'fallbackFile' => '+not-found.html', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-react-native', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'EXPO_PUBLIC_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'EXPO_PUBLIC_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'EXPO_PUBLIC_APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-nextjs', + 'name' => 'Next.js starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple Next.js application integrated with Appwrite SDK.', + 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-nextjs-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-nextjs-light.png', + 'frameworks' => [ + getFramework('NEXTJS', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-nextjs', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'NEXT_PUBLIC_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'NEXT_PUBLIC_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'NEXT_PUBLIC_APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'starter-for-nuxt', + 'name' => 'Nuxt starter', + 'useCases' => [UseCases::STARTER], + 'tagline' => 'Simple Nuxt application integrated with Appwrite SDK.', + 'score' => 3, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'screenshotDark' => $url . '/images/sites/templates/starter-for-nuxt-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/starter-for-nuxt-light.png', + 'frameworks' => [ + getFramework('NUXT', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'starter-for-nuxt', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'NUXT_PUBLIC_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'NUXT_PUBLIC_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'NUXT_PUBLIC_APPWRITE_PROJECT_NAME', + 'description' => 'Your Appwrite project name', + 'value' => '{projectName}', + 'placeholder' => '{projectName}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'template-for-event', + 'name' => 'Event template', + 'tagline' => 'Hackathon landing page with support for project submissions.', + 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::EVENTS], + 'screenshotDark' => $url . '/images/sites/templates/template-for-event-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/template-for-event-light.png', + 'frameworks' => [ + getFramework('NEXTJS', [ + 'providerRootDirectory' => './', + 'installCommand' => 'pnpm install', + 'buildCommand' => 'npm run build', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'template-for-event', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'NEXT_PUBLIC_APPWRITE_FUNCTION_PROJECT_ID', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'NEXT_PUBLIC_APPWRITE_FUNCTION_API_ENDPOINT', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'template-for-portfolio', + 'name' => 'Portfolio template', + 'tagline' => 'Simple personal website to showcase your projects, articles, and more.', + 'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::PORTFOLIO], + 'screenshotDark' => $url . '/images/sites/templates/template-for-portfolio-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/template-for-portfolio-light.png', + 'frameworks' => [ + getFramework('NEXTJS', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'template-for-portfolio', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [] + ], + [ + 'key' => 'template-for-store', + 'name' => 'Store template', + 'tagline' => 'E-commerce platform for selling products with Stripe integration.', + 'score' => 7, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::ECOMMERCE], + 'screenshotDark' => $url . '/images/sites/templates/template-for-store-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/template-for-store-light.png', + 'frameworks' => [ + getFramework('SVELTEKIT', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'template-for-store', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [ + [ + 'name' => 'STRIPE_SECRET_KEY', + 'description' => 'Your Stripe secret key', + 'value' => 'disabled', + 'placeholder' => 'sk_.....', + 'required' => false, + 'type' => 'password' + ], + [ + 'name' => 'PUBLIC_APPWRITE_ENDPOINT', + 'description' => 'Endpoint of Appwrite server', + 'value' => '{apiEndpoint}', + 'placeholder' => '{apiEndpoint}', + 'required' => true, + 'type' => 'text' + ], + [ + 'name' => 'PUBLIC_APPWRITE_PROJECT_ID', + 'description' => 'Your Appwrite project ID', + 'value' => '{projectId}', + 'placeholder' => '{projectId}', + 'required' => true, + 'type' => 'text' + ], + ] + ], + [ + 'key' => 'template-for-blog', + 'name' => 'Blog template', + 'tagline' => 'Platform for publishing written content and media.', + 'score' => 7, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::BLOG], + 'screenshotDark' => $url . '/images/sites/templates/template-for-blog-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/template-for-blog-light.png', + 'frameworks' => [ + getFramework('SVELTEKIT', [ + 'providerRootDirectory' => './', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'template-for-blog', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.1.*', + 'variables' => [] + ], + // TODO: Remove astro starter eventually, or add all frameworks's starters + [ + 'key' => 'astro-starter', + 'name' => 'Astro starter', + 'tagline' => 'Sample application built with Astro, a content-driven web framework.', + '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/astro-starter-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/astro-starter-light.png', + 'frameworks' => [ + getFramework('ASTRO', [ + 'providerRootDirectory' => './astro/starter', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.2.*', + 'variables' => [], + ], + [ + 'key' => 'remix-starter', + 'name' => 'Remix starter', + 'tagline' => 'Sample application built with Remix, a React meta-framework.', + '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/remix-starter-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/remix-starter-light.png', + 'frameworks' => [ + getFramework('REMIX', [ + 'providerRootDirectory' => './remix/starter', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.2.*', + 'variables' => [], + ], +]; diff --git a/app/config/variables.php b/app/config/variables.php index 113fbae335..3083ae893d 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -45,7 +45,16 @@ return [ ], [ 'name' => '_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS', - 'description' => 'Allows you to force HTTPS connection to function domains. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'enabled\'. To disable, set to \'disabled\'. This feature will work only when your ports are set to default 80 and 443.', + 'description' => 'Deprecated since 1.7.0. Allows you to force HTTPS connection to function domains. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'enabled\'. To disable, set to \'disabled\'. This feature will work only when your ports are set to default 80 and 443.', + 'introduction' => '', + 'default' => 'disabled', + 'required' => false, + 'question' => '', + 'filter' => '' + ], + [ + 'name' => '_APP_OPTIONS_ROUTER_FORCE_HTTPS', + 'description' => 'Allows you to force HTTPS connection to function and site domains. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'enabled\'. To disable, set to \'disabled\'. This feature will work only when your ports are set to default 80 and 443.', 'introduction' => '', 'default' => 'disabled', 'required' => false, @@ -90,13 +99,40 @@ return [ ], [ 'name' => '_APP_DOMAIN_TARGET', - 'description' => '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\'.', + '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\'.', 'introduction' => '', 'default' => 'localhost', 'required' => true, 'question' => 'Enter a DNS A record hostname to serve as a CNAME for your custom domains.' . PHP_EOL . 'You can use the same value as used for the Appwrite hostname.', 'filter' => 'domainTarget' ], + [ + 'name' => '_APP_DOMAIN_TARGET_CNAME', + 'description' => 'A domain that can be used as DNS CNAME record to point to instance of Appwrite server.', + 'introduction' => '', + 'default' => 'localhost', + 'required' => false, + 'question' => '', + 'filter' => '' + ], + [ + 'name' => '_APP_DOMAIN_TARGET_AAAA', + 'description' => 'An IPv6 that can be used as DNS AAAA record to point to instance of Appwrite server.', + 'introduction' => '', + 'default' => '::1', + 'required' => false, + 'question' => '', + 'filter' => '' + ], + [ + 'name' => '_APP_DOMAIN_TARGET_A', + 'description' => 'An IPV4 that can be used as DNS A record to point to instance of Appwrite server.', + 'introduction' => '', + 'default' => '127.0.0.1', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_CONSOLE_WHITELIST_ROOT', 'description' => 'This option allows you to disable the creation of new users on the Appwrite console. When enabled only 1 user will be able to use the registration form. New users can be added by inviting them to your project. By default this option is enabled.', @@ -268,6 +304,24 @@ return [ 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_COMPRESSION_ENABLED', + 'description' => 'This option allows you to enable or disable the response compression for the Appwrite API. It\'s enabled by default with value "enabled", and to disable it, pass value "disabled".', + 'introduction' => '1.6.0', + 'default' => 'enabled', + 'required' => false, + 'question' => '', + 'filter' => '' + ], + [ + 'name' => '_APP_COMPRESSION_MIN_SIZE_BYTES', + 'description' => 'This option allows you to set the minimum size in bytes for the response compression to be applied. The default value is 1024 bytes.', + 'introduction' => '1.6.0', + 'default' => 1024, + 'required' => false, + 'question' => '', + 'filter' => '' + ] ], ], [ @@ -554,7 +608,7 @@ return [ ], [ 'name' => '_APP_STORAGE_S3_ACCESS_KEY', - 'description' => 'AWS S3 storage access key. Required when the storage adapter is set to S3. You can get your access key from your AWS console', + 'description' => 'S3 storage access key. Required when the storage adapter is set to S3. You can get your access key from your S3 storage provider', 'introduction' => '0.13.0', 'default' => '', 'required' => false, @@ -562,7 +616,7 @@ return [ ], [ 'name' => '_APP_STORAGE_S3_SECRET', - 'description' => 'AWS S3 storage secret key. Required when the storage adapter is set to S3. You can get your secret key from your AWS console.', + 'description' => 'S3 storage secret key. Required when the storage adapter is set to S3. You can get your secret key from your S3 storage provider.', 'introduction' => '0.13.0', 'default' => '', 'required' => false, @@ -570,7 +624,7 @@ return [ ], [ 'name' => '_APP_STORAGE_S3_REGION', - 'description' => 'AWS S3 storage region. Required when storage adapter is set to S3. You can find your region info for your bucket from AWS console.', + 'description' => 'S3 storage region. Required when storage adapter is set to S3. You can find your region info for your bucket from your S3 storage provider.', 'introduction' => '0.13.0', 'default' => 'us-east-1', 'required' => false, @@ -578,12 +632,20 @@ return [ ], [ 'name' => '_APP_STORAGE_S3_BUCKET', - 'description' => 'AWS S3 storage bucket. Required when storage adapter is set to S3. You can create buckets in your AWS console.', + 'description' => 'S3 storage bucket. Required when storage adapter is set to S3. You can create buckets in your S3 storage provider.', 'introduction' => '0.13.0', 'default' => '', 'required' => false, 'question' => '', ], + [ + 'name' => '_APP_STORAGE_S3_ENDPOINT', + 'description' => 'S3 storage endpoint. Required when using S3 storage providers other than AWS.', + 'introduction' => '0.16.2', + 'default' => '', + 'required' => false, + 'question' => '', + ], [ 'name' => '_APP_STORAGE_DO_SPACES_ACCESS_KEY', 'description' => 'DigitalOcean spaces access key. Required when the storage adapter is set to DOSpaces. You can get your access key from your DigitalOcean console.', @@ -720,13 +782,22 @@ return [ 'variables' => [ [ 'name' => '_APP_FUNCTIONS_SIZE_LIMIT', - 'description' => 'The maximum size of a function in bytes. The default value is 30MB.', + 'description' => 'Deprecated since 1.7.0. The maximum size of a function in bytes. The default value is 30MB.', 'introduction' => '0.13.0', 'default' => '30000000', 'required' => false, 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_COMPUTE_SIZE_LIMIT', + 'description' => 'The maximum size of a function and site deployments in bytes. The default value is 30MB.', + 'introduction' => '1.7.0', + 'default' => '30000000', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_FUNCTIONS_BUILD_SIZE_LIMIT', 'description' => 'The maximum size of a built deployment in bytes. The default value is 2,000,000,000 (2GB), and the maximum value is 4,294,967,295 (4.2GB).', @@ -747,13 +818,22 @@ return [ ], [ 'name' => '_APP_FUNCTIONS_BUILD_TIMEOUT', - 'description' => 'The maximum number of seconds allowed as a timeout value when building a new function. The default value is 900 seconds.', + 'description' => 'Deprecated since 1.7.0. The maximum number of seconds allowed as a timeout value when building a new function. The default value is 900 seconds.', 'introduction' => '0.13.0', 'default' => '900', 'required' => false, 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_COMPUTE_BUILD_TIMEOUT', + 'description' => 'The maximum number of seconds allowed as a timeout value when building a new function or site. The default value is 900 seconds.', + 'introduction' => '1.7.0', + 'default' => '900', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_FUNCTIONS_CONTAINERS', 'description' => 'Deprecated since 1.2.0. Runtimes now timeout by inactivity using \'_APP_FUNCTIONS_INACTIVE_THRESHOLD\'.', @@ -765,22 +845,40 @@ return [ ], [ 'name' => '_APP_FUNCTIONS_CPUS', - 'description' => 'The maximum number of CPU core a single cloud function is allowed to use. Please note that setting a value higher than available cores will result in a function error, which might result in an error. The default value is empty. When it\'s empty, CPU limit will be disabled.', + 'description' => 'Deprecated since 1.7.0. The maximum number of CPU core a single cloud function is allowed to use. Please note that setting a value higher than available cores will result in a function error, which might result in an error. The default value is empty. When it\'s empty, CPU limit will be disabled.', 'introduction' => '0.7.0', 'default' => '0', 'required' => false, 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_COMPUTE_CPUS', + 'description' => 'The maximum number of CPU core a single cloud function or a site is allowed to use. Please note that setting a value higher than available cores might result in an error. The default value is empty. When it\'s empty, CPU limit will be disabled.', + 'introduction' => '1.7.0', + 'default' => '0', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_FUNCTIONS_MEMORY', - 'description' => 'The maximum amount of memory a single cloud function is allowed to use in megabytes. The default value is empty. When it\'s empty, memory limit will be disabled.', + 'description' => 'Deprecated since 1.7.0. The maximum amount of memory a single cloud function is allowed to use in megabytes. The default value is empty. When it\'s empty, memory limit will be disabled.', 'introduction' => '0.7.0', 'default' => '0', 'required' => false, 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_COMPUTE_MEMORY', + 'description' => 'The maximum amount of memory a single function or site is allowed to use in megabytes. The default value is empty. When it\'s empty, memory limit will be disabled.', + 'introduction' => '1.7.0', + 'default' => '0', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_FUNCTIONS_MEMORY_SWAP', 'description' => 'Deprecated since 1.2.0. High use of swap memory is not recommended to preserve harddrive health.', @@ -838,13 +936,22 @@ return [ ], [ 'name' => '_APP_FUNCTIONS_INACTIVE_THRESHOLD', - 'description' => 'The minimum time a function must be inactive before it can be shut down and cleaned up. This feature is intended to clean up unused containers. Containers may remain active for longer than the interval before being shut down, as Appwrite only cleans up unused containers every hour. If no value is provided, the default is 60 seconds.', + 'description' => 'Deprecated since 1.7.0. The minimum time a function must be inactive before it can be shut down and cleaned up. This feature is intended to clean up unused containers. Containers may remain active for longer than the interval before being shut down, as Appwrite only cleans up unused containers every hour. If no value is provided, the default is 60 seconds.', 'introduction' => '0.13.0', 'default' => '60', 'required' => false, 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_COMPUTE_INACTIVE_THRESHOLD', + 'description' => 'The minimum time a function or site must be inactive before it can be shut down and cleaned up. This feature is intended to clean up unused containers. Containers may remain active for longer than the interval before being shut down, as Appwrite only cleans up unused containers every hour. If no value is provided, the default is 60 seconds.', + 'introduction' => '1.7.0', + 'default' => '60', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => 'DOCKERHUB_PULL_USERNAME', 'description' => 'Deprecated with 1.2.0, use \'_APP_DOCKER_HUB_USERNAME\' instead.', @@ -883,13 +990,22 @@ return [ ], [ 'name' => '_APP_FUNCTIONS_RUNTIMES_NETWORK', - 'description' => 'The docker network used for communication between the executor and runtimes.', + 'description' => 'Deprecated since 1.7.0. The docker network used for communication between the executor and runtimes.', 'introduction' => '1.2.0', 'default' => 'runtimes', 'required' => false, 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_COMPUTE_RUNTIMES_NETWORK', + 'description' => 'The docker network used for communication between the executor and runtimes for sites and functions.', + 'introduction' => '1.7.0', + 'default' => 'runtimes', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_DOCKER_HUB_USERNAME', 'description' => 'The username for hub.docker.com. This variable is used to pull images from hub.docker.com.', @@ -910,7 +1026,7 @@ return [ ], [ 'name' => '_APP_FUNCTIONS_MAINTENANCE_INTERVAL', - 'description' => 'Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes. The default value is 3600 seconds (1 hour).', + 'description' => 'Deprecated since 1.7.0. Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes. The default value is 3600 seconds (1 hour).', 'introduction' => '1.4.0', 'default' => '3600', 'required' => false, @@ -918,8 +1034,42 @@ return [ 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_COMPUTE_MAINTENANCE_INTERVAL', + 'description' => 'Interval value containing the number of seconds that the executor should wait before checking for inactive runtimes of functions and sites. The default value is 3600 seconds (1 hour).', + 'introduction' => '1.7.0', + 'default' => '3600', + 'required' => false, + 'overwrite' => true, + 'question' => '', + 'filter' => '' + ], ], ], + [ + 'category' => 'Sites', + 'description' => '', + 'variables' => [ + [ + 'name' => '_APP_SITES_TIMEOUT', + 'description' => 'The maximum number of seconds allowed as a timeout value when creating a new site. The default value is 900 seconds. This is the global limit, timeout for individual functions are configured in the sites\'s settings or in appwrite.json.', + 'introduction' => '1.7.0', + 'default' => '900', + 'required' => false, + 'question' => '', + 'filter' => '' + ], + [ + 'name' => '_APP_SITES_RUNTIMES', + 'description' => "This option allows you to enable or disable runtime environments for Sites. Disable unused runtimes to save disk space.\n\nTo enable cloud site runtimes, pass a list of enabled environments separated by a comma.\n\nCurrently, supported environments are: " . \implode(', ', \array_keys(Config::getParam('runtimes'))), + 'introduction' => '1.7.0', + 'default' => 'static-1,node-22,flutter-3.29', + 'required' => false, + 'question' => '', + 'filter' => '' + ], + ] + ], [ 'category' => 'VCS (Version Control System)', 'description' => '', @@ -1022,13 +1172,22 @@ return [ ], [ 'name' => '_APP_MAINTENANCE_RETENTION_AUDIT', - 'description' => 'IThe maximum duration (in seconds) upto which to retain audit logs. The default value is 1209600 seconds (14 days).', + 'description' => 'The maximum duration (in seconds) upto which to retain audit logs. The default value is 1209600 seconds (14 days).', 'introduction' => '0.7.0', 'default' => '1209600', 'required' => false, 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE', + 'description' => 'The maximum duration (in seconds) upto which to retain console audit logs. The default value is 15778800 seconds (6 months).', + 'introduction' => '1.6.2', + 'default' => '15778800', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_MAINTENANCE_RETENTION_ABUSE', 'description' => 'The maximum duration (in seconds) upto which to retain abuse logs. The default value is 86400 seconds (1 day).', diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 76a3ef8b61..20f64496ac 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -17,17 +17,25 @@ use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Event\Mail; use Appwrite\Event\Messaging; +use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; use Appwrite\Hooks\Hooks; use Appwrite\Network\Validator\Email; use Appwrite\OpenSSL\OpenSSL; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Template\Template; use Appwrite\URL\URL as URLParser; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Identities; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; +use libphonenumber\PhoneNumberUtil; use MaxMind\Db\Reader; +use Utopia\Abuse\Abuse; use Utopia\App; use Utopia\Audit\Audit as EventAudit; use Utopia\Config\Config; @@ -275,17 +283,23 @@ App::post('/v1/account') ->desc('Create account') ->groups(['api', 'account', 'auth']) ->label('scope', 'sessions.write') - ->label('auth.type', 'emailPassword') + ->label('auth.type', 'email-password') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'create') - ->label('sdk.description', '/docs/references/account/create.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'account', + name: 'create', + description: '/docs/references/account/create.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->param('userId', '', new CustomId(), '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.') ->param('email', '', new Email(), 'User email.') @@ -416,15 +430,19 @@ App::get('/v1/account') ->desc('Get account') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/account/get.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'get', + description: '/docs/references/account/get.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { @@ -441,12 +459,19 @@ App::delete('/v1/account') ->label('scope', 'account') ->label('audits.event', 'user.delete') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/account/delete.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'account', + name: 'delete', + description: '/docs/references/account/delete.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->inject('user') ->inject('project') ->inject('response') @@ -486,14 +511,19 @@ App::get('/v1/account/sessions') ->desc('List sessions') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'listSessions') - ->label('sdk.description', '/docs/references/account/list-sessions.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION_LIST) - ->label('sdk.offline.model', '/account/sessions') + ->label('sdk', new Method( + namespace: 'account', + name: 'listSessions', + description: '/docs/references/account/list-sessions.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION_LIST, + ) + ], + contentType: ContentType::JSON, + )) ->inject('response') ->inject('user') ->inject('locale') @@ -530,12 +560,19 @@ App::delete('/v1/account/sessions') ->label('event', 'users.[userId].sessions.[sessionId].delete') ->label('audits.event', 'session.delete') ->label('audits.resource', 'user/{user.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deleteSessions') - ->label('sdk.description', '/docs/references/account/delete-sessions.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'account', + name: 'deleteSessions', + description: '/docs/references/account/delete-sessions.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->label('abuse-limit', 100) ->inject('request') ->inject('response') @@ -592,15 +629,19 @@ App::get('/v1/account/sessions/:sessionId') ->desc('Get session') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'getSession') - ->label('sdk.description', '/docs/references/account/get-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) - ->label('sdk.offline.model', '/account/sessions') - ->label('sdk.offline.key', '{sessionId}') + ->label('sdk', new Method( + namespace: 'account', + name: 'getSession', + description: '/docs/references/account/get-session.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to get the current device session.') ->inject('response') ->inject('user') @@ -641,12 +682,19 @@ App::delete('/v1/account/sessions/:sessionId') ->label('event', 'users.[userId].sessions.[sessionId].delete') ->label('audits.event', 'session.delete') ->label('audits.resource', 'user/{user.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deleteSession') - ->label('sdk.description', '/docs/references/account/delete-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'account', + name: 'deleteSession', + description: '/docs/references/account/delete-session.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->label('abuse-limit', 100) ->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to delete the current device session.') ->inject('requestTimestamp') @@ -722,13 +770,19 @@ App::patch('/v1/account/sessions/:sessionId') ->label('audits.event', 'session.update') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateSession') - ->label('sdk.description', '/docs/references/account/update-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateSession', + description: '/docs/references/account/update-session.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->param('sessionId', '', new UID(), 'Session ID. Use the string \'current\' to update the current device session.') ->inject('response') @@ -796,17 +850,23 @@ App::post('/v1/account/sessions/email') ->groups(['api', 'account', 'auth', 'session']) ->label('event', 'users.[userId].sessions.[sessionId].create') ->label('scope', 'sessions.write') - ->label('auth.type', 'emailPassword') + ->label('auth.type', 'email-password') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createEmailPasswordSession') - ->label('sdk.description', '/docs/references/account/create-session-email-password.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'createEmailPasswordSession', + description: '/docs/references/account/create-session-email-password.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},email:{param-email}') ->param('email', '', new Email(), 'User email.') @@ -934,13 +994,19 @@ App::post('/v1/account/sessions/anonymous') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createAnonymousSession') - ->label('sdk.description', '/docs/references/account/create-session-anonymous.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'createAnonymousSession', + description: '/docs/references/account/create-session-anonymous.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') ->inject('request') @@ -1071,13 +1137,19 @@ App::post('/v1/account/sessions/token') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createSession') - ->label('sdk.description', '/docs/references/account/create-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'createSession', + description: '/docs/references/account/create-session.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'ip:{ip},userId:{param-userId}') ->param('userId', '', new CustomId(), '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.') @@ -1098,14 +1170,21 @@ App::get('/v1/account/sessions/oauth2/:provider') ->groups(['api', 'account']) ->label('error', __DIR__ . '/../../views/general/error.phtml') ->label('scope', 'sessions.write') - ->label('sdk.auth', []) - ->label('sdk.hide', [APP_PLATFORM_SERVER]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createOAuth2Session') - ->label('sdk.description', '/docs/references/account/create-session-oauth2.md') - ->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY) - ->label('sdk.response.type', Response::CONTENT_TYPE_HTML) - ->label('sdk.methodType', 'webAuth') + ->label('sdk', new Method( + namespace: 'account', + name: 'createOAuth2Session', + description: '/docs/references/account/create-session-oauth2.md', + type: MethodType::WEBAUTH, + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_MOVED_PERMANENTLY, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::HTML, + hide: [APP_PLATFORM_SERVER], + )) ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') ->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('oAuthProviders'), fn ($node) => (!$node['mock'])))) . '.') @@ -1688,13 +1767,20 @@ App::get('/v1/account/tokens/oauth2/:provider') ->groups(['api', 'account']) ->label('error', __DIR__ . '/../../views/general/error.phtml') ->label('scope', 'sessions.write') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createOAuth2Token') - ->label('sdk.description', '/docs/references/account/create-token-oauth2.md') - ->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY) - ->label('sdk.response.type', Response::CONTENT_TYPE_HTML) - ->label('sdk.methodType', 'webAuth') + ->label('sdk', new Method( + namespace: 'account', + name: 'createOAuth2Token', + description: '/docs/references/account/create-token-oauth2.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_MOVED_PERMANENTLY, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::HTML, + type: MethodType::WEBAUTH, + )) ->label('abuse-limit', 50) ->label('abuse-key', 'ip:{ip}') ->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('oAuthProviders'), fn ($node) => (!$node['mock'])))) . '.') @@ -1761,13 +1847,19 @@ App::post('/v1/account/tokens/magic-url') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createMagicURLToken') - ->label('sdk.description', '/docs/references/account/create-token-magic-url.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createMagicURLToken', + description: '/docs/references/account/create-token-magic-url.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 60) ->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}']) ->param('userId', '', new CustomId(), '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.') @@ -2004,13 +2096,19 @@ App::post('/v1/account/tokens/email') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createEmailToken') - ->label('sdk.description', '/docs/references/account/create-token-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createEmailToken', + description: '/docs/references/account/create-token-email.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},email:{param-email}') ->param('userId', '', new CustomId(), '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.') @@ -2233,14 +2331,20 @@ App::put('/v1/account/sessions/magic-url') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.deprecated', true) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateMagicURLSession') - ->label('sdk.description', '/docs/references/account/create-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateMagicURLSession', + description: '/docs/references/account/create-session.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON, + deprecated: true, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'ip:{ip},userId:{param-userId}') ->param('userId', '', new CustomId(), '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.') @@ -2264,14 +2368,20 @@ App::put('/v1/account/sessions/phone') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.deprecated', true) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePhoneSession') - ->label('sdk.description', '/docs/references/account/create-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePhoneSession', + description: '/docs/references/account/create-session.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON, + deprecated: true, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'ip:{ip},userId:{param-userId}') ->param('userId', '', new CustomId(), '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.') @@ -2290,19 +2400,25 @@ App::put('/v1/account/sessions/phone') App::post('/v1/account/tokens/phone') ->alias('/v1/account/sessions/phone') ->desc('Create phone token') - ->groups(['api', 'account']) + ->groups(['api', 'account', 'auth']) ->label('scope', 'sessions.write') ->label('auth.type', 'phone') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createPhoneToken') - ->label('sdk.description', '/docs/references/account/create-token-phone.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createPhoneToken', + description: '/docs/references/account/create-token-phone.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', ['url:{url},phone:{param-phone}', 'url:{url},ip:{ip}']) ->param('userId', '', new CustomId(), '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.') @@ -2315,7 +2431,10 @@ App::post('/v1/account/tokens/phone') ->inject('queueForEvents') ->inject('queueForMessaging') ->inject('locale') - ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale) { + ->inject('timelimit') + ->inject('queueForStatsUsage') + ->inject('plan') + ->action(function (string $userId, string $phone, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -2452,6 +2571,27 @@ App::post('/v1/account/tokens/phone') ->setMessage($messageDoc) ->setRecipients([$phone]) ->setProviderType(MESSAGE_TYPE_SMS); + + if (isset($plan['authPhone'])) { + $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days + $timelimit + ->setParam('{organizationId}', $project->getAttribute('teamId')); + + $abuse = new Abuse($timelimit); + if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { + $helper = PhoneNumberUtil::getInstance(); + $countryCode = $helper->parse($phone)->getCountryCode(); + + if (!empty($countryCode)) { + $queueForStatsUsage + ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); + } + } + $queueForStatsUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); + } } // Set to unhashed secret for events and server responses @@ -2474,13 +2614,19 @@ App::post('/v1/account/jwts') ->groups(['api', 'account', 'auth']) ->label('scope', 'account') ->label('auth.type', 'jwt') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createJWT') - ->label('sdk.description', '/docs/references/account/create-jwt.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_JWT) + ->label('sdk', new Method( + namespace: 'account', + name: 'createJWT', + description: '/docs/references/account/create-jwt.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_JWT, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 100) ->label('abuse-key', 'url:{url},userId:{userId}') ->inject('response') @@ -2516,15 +2662,19 @@ App::get('/v1/account/prefs') ->desc('Get account preferences') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'getPrefs') - ->label('sdk.description', '/docs/references/account/get-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PREFERENCES) - ->label('sdk.offline.model', '/account/prefs') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'getPrefs', + description: '/docs/references/account/get-prefs.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PREFERENCES, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { @@ -2538,13 +2688,19 @@ App::get('/v1/account/logs') ->desc('List logs') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'listLogs') - ->label('sdk.description', '/docs/references/account/list-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'account', + name: 'listLogs', + description: '/docs/references/account/list-logs.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON, + )) ->param('queries', [], new Queries([new Limit(), new Offset()]), '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', true) ->inject('response') ->inject('user') @@ -2559,13 +2715,15 @@ App::get('/v1/account/logs') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $grouped = Query::groupByType($queries); - $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; - $offset = $grouped['offset'] ?? 0; + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); $audit = new EventAudit($dbForProject); - $logs = $audit->getLogsByUser($user->getInternalId(), $limit, $offset); + $logs = $audit->getLogsByUser($user->getInternalId(), $queries); $output = []; @@ -2594,7 +2752,7 @@ App::get('/v1/account/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getInternalId()), + 'total' => $audit->countLogsByUser($user->getInternalId(), $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -2606,15 +2764,19 @@ App::patch('/v1/account/name') ->label('scope', 'account') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateName') - ->label('sdk.description', '/docs/references/account/update-name.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updateName', + description: '/docs/references/account/update-name.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('name', '', new Text(128), 'User name. Max length: 128 chars.') ->inject('requestTimestamp') ->inject('response') @@ -2640,15 +2802,19 @@ App::patch('/v1/account/password') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePassword') - ->label('sdk.description', '/docs/references/account/update-password.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePassword', + description: '/docs/references/account/update-password.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, $project->getAttribute('auths', [])['passwordDictionary'] ?? false), 'New user password. Must be at least 8 chars.', false, ['project', 'passwordsDictionary']) ->param('oldPassword', '', new Password(), 'Current user password. Must be at least 8 chars.', true) @@ -2709,15 +2875,19 @@ App::patch('/v1/account/email') ->label('scope', 'account') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateEmail') - ->label('sdk.description', '/docs/references/account/update-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updateEmail', + description: '/docs/references/account/update-email.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password. Must be at least 8 chars.') ->inject('requestTimestamp') @@ -2801,15 +2971,19 @@ App::patch('/v1/account/phone') ->label('scope', 'account') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePhone') - ->label('sdk.description', '/docs/references/account/update-phone.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePhone', + description: '/docs/references/account/update-phone.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.') ->param('password', '', new Password(), 'User password. Must be at least 8 chars.') ->inject('requestTimestamp') @@ -2882,15 +3056,19 @@ App::patch('/v1/account/prefs') ->label('scope', 'account') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePrefs') - ->label('sdk.description', '/docs/references/account/update-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account/prefs') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePrefs', + description: '/docs/references/account/update-prefs.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('prefs', [], new Assoc(), 'Prefs key-value JSON object.') ->inject('requestTimestamp') ->inject('response') @@ -2915,13 +3093,19 @@ App::patch('/v1/account/status') ->label('scope', 'account') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateStatus') - ->label('sdk.description', '/docs/references/account/update-status.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateStatus', + description: '/docs/references/account/update-status.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON, + )) ->inject('requestTimestamp') ->inject('request') ->inject('response') @@ -2959,13 +3143,19 @@ App::post('/v1/account/recovery') ->label('audits.event', 'recovery.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createRecovery') - ->label('sdk.description', '/docs/references/account/create-recovery.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createRecovery', + description: '/docs/references/account/create-recovery.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', ['url:{url},email:{param-email}', 'url:{url},ip:{ip}']) ->param('email', '', new Email(), 'User email.') @@ -3139,13 +3329,19 @@ App::put('/v1/account/recovery') ->label('audits.event', 'recovery.update') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateRecovery') - ->label('sdk.description', '/docs/references/account/update-recovery.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateRecovery', + description: '/docs/references/account/update-recovery.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{param-userId}') ->param('userId', '', new UID(), 'User ID.') @@ -3223,13 +3419,19 @@ App::post('/v1/account/verification') ->label('event', 'users.[userId].verification.[tokenId].create') ->label('audits.event', 'verification.create') ->label('audits.resource', 'user/{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createVerification') - ->label('sdk.description', '/docs/references/account/create-email-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createVerification', + description: '/docs/references/account/create-email-verification.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') ->param('url', '', fn ($clients) => new Host($clients), '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.', false, ['clients']) // TODO add built-in confirm page @@ -3388,13 +3590,19 @@ App::put('/v1/account/verification') ->label('event', 'users.[userId].verification.[tokenId].update') ->label('audits.event', 'verification.update') ->label('audits.resource', 'user/{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateVerification') - ->label('sdk.description', '/docs/references/account/update-email-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateVerification', + description: '/docs/references/account/update-email-verification.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{param-userId}') ->param('userId', '', new UID(), 'User ID.') @@ -3448,13 +3656,19 @@ App::post('/v1/account/verification/phone') ->label('event', 'users.[userId].verification.[tokenId].create') ->label('audits.event', 'verification.create') ->label('audits.resource', 'user/{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createPhoneVerification') - ->label('sdk.description', '/docs/references/account/create-phone-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'createPhoneVerification', + description: '/docs/references/account/create-phone-verification.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', ['url:{url},userId:{userId}', 'url:{url},ip:{ip}']) ->inject('request') @@ -3465,7 +3679,10 @@ App::post('/v1/account/verification/phone') ->inject('queueForMessaging') ->inject('project') ->inject('locale') - ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale) { + ->inject('timelimit') + ->inject('queueForStatsUsage') + ->inject('plan') + ->action(function (Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents, Messaging $queueForMessaging, Document $project, Locale $locale, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); } @@ -3548,6 +3765,27 @@ App::post('/v1/account/verification/phone') ->setMessage($messageDoc) ->setRecipients([$user->getAttribute('phone')]) ->setProviderType(MESSAGE_TYPE_SMS); + + if (isset($plan['authPhone'])) { + $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days + $timelimit + ->setParam('{organizationId}', $project->getAttribute('teamId')); + + $abuse = new Abuse($timelimit); + if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { + $helper = PhoneNumberUtil::getInstance(); + $countryCode = $helper->parse($phone)->getCountryCode(); + + if (!empty($countryCode)) { + $queueForStatsUsage + ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); + } + } + $queueForStatsUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); + } } // Set to unhashed secret for events and server responses @@ -3575,13 +3813,19 @@ App::put('/v1/account/verification/phone') ->label('event', 'users.[userId].verification.[tokenId].update') ->label('audits.event', 'verification.update') ->label('audits.resource', 'user/{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePhoneVerification') - ->label('sdk.description', '/docs/references/account/update-phone-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePhoneVerification', + description: '/docs/references/account/update-phone-verification.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOKEN, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'userId:{param-userId}') ->param('userId', '', new UID(), 'User ID.') @@ -3634,15 +3878,19 @@ App::patch('/v1/account/mfa') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateMFA') - ->label('sdk.description', '/docs/references/account/update-mfa.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updateMFA', + description: '/docs/references/account/update-mfa.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('mfa', null, new Boolean(), 'Enable or disable MFA.') ->inject('requestTimestamp') ->inject('response') @@ -3683,15 +3931,19 @@ App::get('/v1/account/mfa/factors') ->desc('List factors') ->groups(['api', 'account', 'mfa']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'listMfaFactors') - ->label('sdk.description', '/docs/references/account/list-mfa-factors.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_FACTORS) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'listMfaFactors', + description: '/docs/references/account/list-mfa-factors.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_FACTORS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { @@ -3719,15 +3971,19 @@ App::post('/v1/account/mfa/authenticators/:type') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createMfaAuthenticator') - ->label('sdk.description', '/docs/references/account/create-mfa-authenticator.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_TYPE) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'createMfaAuthenticator', + description: '/docs/references/account/create-mfa-authenticator.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_TYPE, + ) + ], + contentType: ContentType::JSON + )) ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator. Must be `' . Type::TOTP . '`') ->inject('requestTimestamp') ->inject('response') @@ -3791,15 +4047,19 @@ App::put('/v1/account/mfa/authenticators/:type') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateMfaAuthenticator') - ->label('sdk.description', '/docs/references/account/update-mfa-authenticator.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updateMfaAuthenticator', + description: '/docs/references/account/update-mfa-authenticator.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ], + contentType: ContentType::JSON + )) ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator.') ->param('otp', '', new Text(256), 'Valid verification token.') ->inject('response') @@ -3856,15 +4116,19 @@ App::post('/v1/account/mfa/recovery-codes') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/account/create-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'createMfaRecoveryCodes', + description: '/docs/references/account/create-mfa-recovery-codes.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->inject('dbForProject') @@ -3898,15 +4162,19 @@ App::patch('/v1/account/mfa/recovery-codes') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/account/update-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'updateMfaRecoveryCodes', + description: '/docs/references/account/update-mfa-recovery-codes.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ], + contentType: ContentType::JSON + )) ->inject('dbForProject') ->inject('response') ->inject('user') @@ -3935,15 +4203,19 @@ App::get('/v1/account/mfa/recovery-codes') ->desc('Get MFA recovery codes') ->groups(['api', 'account', 'mfaProtected']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'getMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/account/get-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) - ->label('sdk.offline.model', '/account') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'account', + name: 'getMfaRecoveryCodes', + description: '/docs/references/account/get-mfa-recovery-codes.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('user') ->action(function (Response $response, Document $user) { @@ -3969,12 +4241,19 @@ App::delete('/v1/account/mfa/authenticators/:type') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deleteMfaAuthenticator') - ->label('sdk.description', '/docs/references/account/delete-mfa-authenticator.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'account', + name: 'deleteMfaAuthenticator', + description: '/docs/references/account/delete-mfa-authenticator.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator.') ->inject('response') ->inject('user') @@ -4007,13 +4286,19 @@ App::post('/v1/account/mfa/challenge') ->label('audits.event', 'challenge.create') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', []) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createMfaChallenge') - ->label('sdk.description', '/docs/references/account/create-mfa-challenge.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_CHALLENGE) + ->label('sdk', new Method( + namespace: 'account', + name: 'createMfaChallenge', + description: '/docs/references/account/create-mfa-challenge.md', + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MFA_CHALLENGE, + ) + ], + contentType: ContentType::JSON, + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},userId:{userId}') ->param('factor', '', new WhiteList([Type::EMAIL, Type::PHONE, Type::TOTP, Type::RECOVERY_CODE]), 'Factor used for verification. Must be one of following: `' . Type::EMAIL . '`, `' . Type::PHONE . '`, `' . Type::TOTP . '`, `' . Type::RECOVERY_CODE . '`.') @@ -4026,7 +4311,10 @@ App::post('/v1/account/mfa/challenge') ->inject('queueForEvents') ->inject('queueForMessaging') ->inject('queueForMails') - ->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Locale $locale, Document $project, Request $request, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails) { + ->inject('timelimit') + ->inject('queueForStatsUsage') + ->inject('plan') + ->action(function (string $factor, Response $response, Database $dbForProject, Document $user, Locale $locale, Document $project, Request $request, Event $queueForEvents, Messaging $queueForMessaging, Mail $queueForMails, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { $expire = DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_CONFIRM); $code = Auth::codeGenerator(); @@ -4074,6 +4362,7 @@ App::post('/v1/account/mfa/challenge') $message = $message->render(); + $phone = $user->getAttribute('phone'); $queueForMessaging ->setType(MESSAGE_SEND_TYPE_INTERNAL) ->setMessage(new Document([ @@ -4082,8 +4371,29 @@ App::post('/v1/account/mfa/challenge') 'content' => $code, ], ])) - ->setRecipients([$user->getAttribute('phone')]) + ->setRecipients([$phone]) ->setProviderType(MESSAGE_TYPE_SMS); + + if (isset($plan['authPhone'])) { + $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days + $timelimit + ->setParam('{organizationId}', $project->getAttribute('teamId')); + + $abuse = new Abuse($timelimit); + if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { + $helper = PhoneNumberUtil::getInstance(); + $countryCode = $helper->parse($phone)->getCountryCode(); + + if (!empty($countryCode)) { + $queueForStatsUsage + ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); + } + } + $queueForStatsUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); + } break; case Type::EMAIL: if (empty(System::getEnv('_APP_SMTP_HOST'))) { @@ -4195,12 +4505,19 @@ App::put('/v1/account/mfa/challenge') ->label('audits.event', 'challenges.update') ->label('audits.resource', 'user/{response.userId}') ->label('audits.userId', '{response.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updateMfaChallenge') - ->label('sdk.description', '/docs/references/account/update-mfa-challenge.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'account', + name: 'updateMfaChallenge', + description: '/docs/references/account/update-mfa-challenge.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION, + ) + ], + contentType: ContentType::JSON + )) ->label('abuse-limit', 10) ->label('abuse-key', 'url:{url},challengeId:{param-challengeId}') ->param('challengeId', '', new Text(256), 'ID of the challenge.') @@ -4281,12 +4598,19 @@ App::post('/v1/account/targets/push') ->label('audits.event', 'target.create') ->label('audits.resource', 'target/response.$id') ->label('event', 'users.[userId].targets.[targetId].create') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'createPushTarget') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'account', + name: 'createPushTarget', + description: '/docs/references/account/create-push-target.md', + auth: [AuthType::SESSION], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TARGET, + ) + ], + contentType: ContentType::JSON + )) ->param('targetId', '', new CustomId(), '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.') ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)') ->param('providerId', '', new UID(), '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.', true) @@ -4354,12 +4678,19 @@ App::put('/v1/account/targets/:targetId/push') ->label('audits.event', 'target.update') ->label('audits.resource', 'target/response.$id') ->label('event', 'users.[userId].targets.[targetId].update') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'updatePushTarget') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'account', + name: 'updatePushTarget', + description: '/docs/references/account/update-push-target.md', + auth: [AuthType::SESSION], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TARGET, + ) + ], + contentType: ContentType::JSON + )) ->param('targetId', '', new UID(), 'Target ID.') ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)') ->inject('queueForEvents') @@ -4411,12 +4742,19 @@ App::delete('/v1/account/targets/:targetId/push') ->label('audits.event', 'target.delete') ->label('audits.resource', 'target/response.$id') ->label('event', 'users.[userId].targets.[targetId].delete') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deletePushTarget') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'account', + name: 'deletePushTarget', + description: '/docs/references/account/delete-push-target.md', + auth: [AuthType::SESSION], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('targetId', '', new UID(), 'Target ID.') ->inject('queueForEvents') ->inject('queueForDeletes') @@ -4454,14 +4792,19 @@ App::get('/v1/account/identities') ->desc('List identities') ->groups(['api', 'account']) ->label('scope', 'account') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'listIdentities') - ->label('sdk.description', '/docs/references/account/list-identities.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_IDENTITY_LIST) - ->label('sdk.offline.model', '/account/identities') + ->label('sdk', new Method( + namespace: 'account', + name: 'listIdentities', + description: '/docs/references/account/list-identities.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_IDENTITY_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('user') @@ -4520,12 +4863,19 @@ App::delete('/v1/account/identities/:identityId') ->label('audits.event', 'identity.delete') ->label('audits.resource', 'identity/{request.$identityId}') ->label('audits.userId', '{user.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'account') - ->label('sdk.method', 'deleteIdentity') - ->label('sdk.description', '/docs/references/account/delete-identity.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'account', + name: 'deleteIdentity', + description: '/docs/references/account/delete-identity.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('identityId', '', new UID(), 'Identity ID.') ->inject('response') ->inject('dbForProject') diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index dadd9da5e3..120383fa4d 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -1,6 +1,11 @@ <?php use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\URL\URL as URLParse; use Appwrite\Utopia\Response; use chillerlan\QRCode\QRCode; @@ -61,9 +66,9 @@ $avatarCallback = function (string $type, string $code, int $width, int $height, unset($image); }; -$getUserGitHub = function (string $userId, Document $project, Database $dbForProject, Database $dbForConsole, ?Logger $logger) { +$getUserGitHub = function (string $userId, Document $project, Database $dbForProject, Database $dbForPlatform, ?Logger $logger) { try { - $user = Authorization::skip(fn () => $dbForConsole->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); @@ -122,7 +127,7 @@ $getUserGitHub = function (string $userId, Document $project, Database $dbForPro do { $previousAccessToken = $gitHubSession->getAttribute('providerAccessToken'); - $user = Authorization::skip(fn () => $dbForConsole->getDocument('users', $userId)); + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); $sessions = $user->getAttribute('sessions', []); $gitHubSession = new Document(); @@ -164,13 +169,20 @@ App::get('/v1/avatars/credit-cards/:code') ->label('scope', 'avatars.read') ->label('cache', true) ->label('cache.resource', 'avatar/credit-card') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getCreditCard') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-credit-card.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getCreditCard', + description: '/docs/references/avatars/get-credit-card.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE_PNG + )) ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-credit-cards'))), 'Credit Card Code. Possible values: ' . \implode(', ', \array_keys(Config::getParam('avatar-credit-cards'))) . '.') ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) @@ -184,13 +196,20 @@ App::get('/v1/avatars/browsers/:code') ->label('scope', 'avatars.read') ->label('cache', true) ->label('cache.resource', 'avatar/browser') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getBrowser') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-browser.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getBrowser', + description: '/docs/references/avatars/get-browser.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE_PNG + )) ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-browsers'))), 'Browser Code.') ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) @@ -204,13 +223,20 @@ App::get('/v1/avatars/flags/:code') ->label('scope', 'avatars.read') ->label('cache', true) ->label('cache.resource', 'avatar/flag') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getFlag') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-flag.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getFlag', + description: '/docs/references/avatars/get-flag.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE_PNG + )) ->param('code', '', new WhiteList(\array_keys(Config::getParam('avatar-flags'))), 'Country Code. ISO Alpha-2 country code format.') ->param('width', 100, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 100, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) @@ -224,13 +250,20 @@ App::get('/v1/avatars/image') ->label('scope', 'avatars.read') ->label('cache', true) ->label('cache.resource', 'avatar/image') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getImage') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-image.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getImage', + description: '/docs/references/avatars/get-image.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE + )) ->param('url', '', new URL(['http', 'https']), 'Image URL which you want to crop.') ->param('width', 400, new Range(0, 2000), 'Resize preview image width, Pass an integer between 0 to 2000. Defaults to 400.', true) ->param('height', 400, new Range(0, 2000), 'Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.', true) @@ -287,13 +320,20 @@ App::get('/v1/avatars/favicon') ->label('scope', 'avatars.read') ->label('cache', true) ->label('cache.resource', 'avatar/favicon') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getFavicon') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-favicon.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getFavicon', + description: '/docs/references/avatars/get-favicon.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE + )) ->param('url', '', new URL(['http', 'https']), 'Website URL which you want to fetch the favicon from.') ->inject('response') ->action(function (string $url, Response $response) { @@ -430,13 +470,20 @@ App::get('/v1/avatars/qr') ->desc('Get QR code') ->groups(['api', 'avatars']) ->label('scope', 'avatars.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getQR') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-qr.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getQR', + description: '/docs/references/avatars/get-qr.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE_PNG + )) ->param('text', '', new Text(512), 'Plain text to be converted to QR code image.') ->param('size', 400, new Range(1, 1000), 'QR code size. Pass an integer between 1 to 1000. Defaults to 400.', true) ->param('margin', 1, new Range(0, 10), 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true) @@ -449,6 +496,7 @@ App::get('/v1/avatars/qr') 'addQuietzone' => true, 'quietzoneSize' => $margin, 'outputType' => QRCode::OUTPUT_IMAGICK, + 'scale' => 15, ]); $qrcode = new QRCode($options); @@ -463,7 +511,7 @@ App::get('/v1/avatars/qr') $response ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days ->setContentType('image/png') - ->send($image->output('png', 9)); + ->send($image->output('png', 90)); }); App::get('/v1/avatars/initials') @@ -471,13 +519,20 @@ App::get('/v1/avatars/initials') ->groups(['api', 'avatars']) ->label('scope', 'avatars.read') ->label('cache.resource', 'avatar/initials') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'avatars') - ->label('sdk.method', 'getInitials') - ->label('sdk.methodType', 'location') - ->label('sdk.description', '/docs/references/avatars/get-initials.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE_PNG) + ->label('sdk', new Method( + namespace: 'avatars', + name: 'getInitials', + description: '/docs/references/avatars/get-initials.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + type: MethodType::LOCATION, + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::IMAGE_PNG + )) ->param('name', '', new Text(128), 'Full Name. When empty, current user name or email will be used. Max length: 128 chars.', true) ->param('width', 500, new Range(0, 2000), 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true) ->param('height', 500, new Range(0, 2000), 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true) @@ -565,14 +620,14 @@ App::get('/v1/cards/cloud') ->inject('user') ->inject('project') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('response') ->inject('heroes') ->inject('contributors') ->inject('employees') ->inject('logger') - ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { - $user = Authorization::skip(fn () => $dbForConsole->getDocument('users', $userId)); + ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -583,7 +638,7 @@ App::get('/v1/cards/cloud') $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; @@ -772,14 +827,14 @@ App::get('/v1/cards/cloud-back') ->inject('user') ->inject('project') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('response') ->inject('heroes') ->inject('contributors') ->inject('employees') ->inject('logger') - ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { - $user = Authorization::skip(fn () => $dbForConsole->getDocument('users', $userId)); + ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -789,7 +844,7 @@ App::get('/v1/cards/cloud-back') $userId = $user->getId(); $email = $user->getAttribute('email', ''); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubId = $gitHub['id'] ?? ''; $isHero = \array_key_exists($email, $heroes); @@ -850,14 +905,14 @@ App::get('/v1/cards/cloud-og') ->inject('user') ->inject('project') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('response') ->inject('heroes') ->inject('contributors') ->inject('employees') ->inject('logger') - ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForConsole, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { - $user = Authorization::skip(fn () => $dbForConsole->getDocument('users', $userId)); + ->action(function (string $userId, string $mock, int $width, int $height, Document $user, Document $project, Database $dbForProject, Database $dbForPlatform, Response $response, array $heroes, array $contributors, array $employees, ?Logger $logger) use ($getUserGitHub) { + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); if ($user->isEmpty() && empty($mock)) { throw new Exception(Exception::USER_NOT_FOUND); @@ -872,7 +927,7 @@ App::get('/v1/cards/cloud-og') $email = $user->getAttribute('email', ''); $createdAt = new \DateTime($user->getCreatedAt()); - $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForConsole, $logger); + $gitHub = $getUserGitHub($user->getId(), $project, $dbForProject, $dbForPlatform, $logger); $githubName = $gitHub['name'] ?? ''; $githubId = $gitHub['id'] ?? ''; diff --git a/app/controllers/api/console.php b/app/controllers/api/console.php index eeb823a3d3..4dd5432d3a 100644 --- a/app/controllers/api/console.php +++ b/app/controllers/api/console.php @@ -1,10 +1,16 @@ <?php use Appwrite\Extend\Exception; +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\Database\Document; +use Utopia\Domains\Domain; use Utopia\System\System; +use Utopia\Validator\IP; use Utopia\Validator\Text; App::init() @@ -21,19 +27,36 @@ App::get('/v1/console/variables') ->desc('Get variables') ->groups(['api', 'projects']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'console') - ->label('sdk.method', 'variables') - ->label('sdk.description', '/docs/references/console/variables.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_CONSOLE_VARIABLES) + ->label('sdk', new Method( + namespace: 'console', + name: 'variables', + description: '/docs/references/console/variables.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_CONSOLE_VARIABLES, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->action(function (Response $response) { - $isDomainEnabled = !empty(System::getEnv('_APP_DOMAIN', '')) - && !empty(System::getEnv('_APP_DOMAIN_TARGET', '')) - && System::getEnv('_APP_DOMAIN', '') !== 'localhost' - && System::getEnv('_APP_DOMAIN_TARGET', '') !== 'localhost'; + $validator = new Domain(System::getEnv('_APP_DOMAIN')); + $isDomainValid = !empty(System::getEnv('_APP_DOMAIN', '')) && $validator->isKnown() && !$validator->isTest(); + + $validator = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME')); + $isCNAMEValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')) && $validator->isKnown() && !$validator->isTest(); + + $validator = new IP(IP::V4); + $isAValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_A', '')) && ($validator->isValid(System::getEnv('_APP_DOMAIN_TARGET_A'))); + + $validator = new IP(IP::V6); + $isAAAAValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_AAAA', '')) && $validator->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA')); + + $isDomainEnabled = $isDomainValid && ( + $isAAAAValid || $isAValid || $isCNAMEValid + ); $isVcsEnabled = !empty(System::getEnv('_APP_VCS_GITHUB_APP_NAME', '')) && !empty(System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY', '')) @@ -44,13 +67,19 @@ App::get('/v1/console/variables') $isAssistantEnabled = !empty(System::getEnv('_APP_ASSISTANT_OPENAI_API_KEY', '')); $variables = new Document([ - '_APP_DOMAIN_TARGET' => System::getEnv('_APP_DOMAIN_TARGET'), + '_APP_DOMAIN_TARGET_CNAME' => System::getEnv('_APP_DOMAIN_TARGET_CNAME'), + '_APP_DOMAIN_TARGET_AAAA' => System::getEnv('_APP_DOMAIN_TARGET_AAAA'), + '_APP_DOMAIN_TARGET_A' => System::getEnv('_APP_DOMAIN_TARGET_A'), '_APP_STORAGE_LIMIT' => +System::getEnv('_APP_STORAGE_LIMIT'), - '_APP_FUNCTIONS_SIZE_LIMIT' => +System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT'), + '_APP_COMPUTE_SIZE_LIMIT' => +System::getEnv('_APP_COMPUTE_SIZE_LIMIT'), '_APP_USAGE_STATS' => System::getEnv('_APP_USAGE_STATS'), '_APP_VCS_ENABLED' => $isVcsEnabled, '_APP_DOMAIN_ENABLED' => $isDomainEnabled, - '_APP_ASSISTANT_ENABLED' => $isAssistantEnabled + '_APP_ASSISTANT_ENABLED' => $isAssistantEnabled, + '_APP_DOMAIN_SITES' => System::getEnv('_APP_DOMAIN_SITES'), + '_APP_DOMAIN_FUNCTIONS' => System::getEnv('_APP_DOMAIN_FUNCTIONS'), + '_APP_OPTIONS_FORCE_HTTPS' => System::getEnv('_APP_OPTIONS_FORCE_HTTPS'), + '_APP_DOMAINS_NAMESERVERS' => System::getEnv('_APP_DOMAINS_NAMESERVERS'), ]); $response->dynamic($variables, Response::MODEL_CONSOLE_VARIABLES); @@ -60,18 +89,25 @@ App::post('/v1/console/assistant') ->desc('Ask query') ->groups(['api', 'assistant']) ->label('scope', 'assistant.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'assistant') - ->label('sdk.method', 'chat') - ->label('sdk.description', '/docs/references/assistant/chat.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_TEXT) + ->label('sdk', new Method( + namespace: 'assistant', + name: 'chat', + description: '/docs/references/assistant/chat.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::TEXT + )) ->label('abuse-limit', 15) ->label('abuse-key', 'userId:{userId}') ->param('prompt', '', new Text(2000), 'Prompt. A string containing questions asked to the AI assistant.') ->inject('response') ->action(function (string $prompt, Response $response) { - $ch = curl_init('http://appwrite-assistant:3003/'); + $ch = curl_init('http://appwrite-assistant:3003/v1/models/assistant/prompt'); $responseHeaders = []; $query = json_encode(['prompt' => $prompt]); $headers = ['accept: text/event-stream']; diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 0114fd343c..0c37e1a765 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4,9 +4,13 @@ use Appwrite\Auth\Auth; use Appwrite\Detector\Detector; use Appwrite\Event\Database as EventDatabase; use Appwrite\Event\Event; -use Appwrite\Event\Usage; +use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Attributes; use Appwrite\Utopia\Database\Validator\Queries\Collections; @@ -19,11 +23,12 @@ use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; use Utopia\Database\Database; +use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Duplicate as DuplicateException; +use Utopia\Database\Exception\Index as IndexException; use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Query as QueryException; @@ -37,6 +42,7 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\Index as IndexValidator; +use Utopia\Database\Validator\IndexDependency as IndexDependencyValidator; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\Queries; @@ -153,7 +159,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att } catch (DuplicateException) { throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); } catch (LimitException) { - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); } catch (\Throwable $e) { $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); @@ -197,7 +203,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); } catch (LimitException) { $dbForProject->deleteDocument('attributes', $attribute->getId()); - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); } catch (\Throwable $e) { $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); @@ -237,8 +243,8 @@ function updateAttribute( string $filter = null, string|bool|int|float $default = null, bool $required = null, - int|float $min = null, - int|float $max = null, + int|float|null $min = null, + int|float|null $max = null, array $elements = null, array $options = [], string $newKey = null, @@ -291,14 +297,11 @@ function updateAttribute( $attribute->setAttribute('size', $size); } - $formatOptions = $attribute->getAttribute('formatOptions'); - switch ($attribute->getAttribute('format')) { case APP_DATABASE_ATTRIBUTE_INT_RANGE: case APP_DATABASE_ATTRIBUTE_FLOAT_RANGE: - if ($min === $formatOptions['min'] && $max === $formatOptions['max']) { - break; - } + $min ??= $attribute->getAttribute('formatOptions')['min']; + $max ??= $attribute->getAttribute('formatOptions')['max']; if ($min > $max) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); @@ -386,30 +389,44 @@ function updateAttribute( size: $size, required: $required, default: $default, - formatOptions: $options ?? null, + formatOptions: $options, newKey: $newKey ?? null ); } catch (TruncateException) { throw new Exception(Exception::ATTRIBUTE_INVALID_RESIZE); } catch (NotFoundException) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } catch (LimitException) { + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); + } catch (IndexException $e) { + throw new Exception(Exception::INDEX_INVALID, $e->getMessage()); } } if (!empty($newKey) && $key !== $newKey) { - // Delete attribute and recreate since we can't modify IDs - $original = clone $attribute; - - $dbForProject->deleteDocument('attributes', $attribute->getId()); + $originalUid = $attribute->getId(); $attribute ->setAttribute('$id', ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $newKey)) ->setAttribute('key', $newKey); - try { - $attribute = $dbForProject->createDocument('attributes', $attribute); - } catch (DatabaseException|PDOException) { - $attribute = $dbForProject->createDocument('attributes', $original); + $dbForProject->updateDocument('attributes', $originalUid, $attribute); + + /** + * @var Document $index + */ + foreach ($collection->getAttribute('indexes') as $index) { + /** + * @var string[] $attributes + */ + $attributes = $index->getAttribute('attributes', []); + $found = \array_search($key, $attributes); + + if ($found !== false) { + $attributes[$found] = $newKey; + $index->setAttribute('attributes', $attributes); + $dbForProject->updateDocument('indexes', $index->getId(), $index); + } } } else { $attribute = $dbForProject->updateDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); @@ -447,21 +464,27 @@ App::post('/v1/databases') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'database.create') ->label('audits.resource', 'database/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'create') - ->label('sdk.description', '/docs/references/databases/create.md') // create this file later - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DATABASE) // Model for database needs to be created + ->label('sdk', new Method( + namespace: 'databases', + name: 'create', + description: '/docs/references/databases/create.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_DATABASE, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Database name. Max length: 128 chars.') ->param('enabled', true, new Boolean(), '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.', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('queueForUsage') - ->action(function (string $databaseId, string $name, bool $enabled, Response $response, Database $dbForProject, Event $queueForEvents, Usage $queueForUsage) { + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, string $name, bool $enabled, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { $databaseId = $databaseId == 'unique()' ? ID::unique() : $databaseId; @@ -511,7 +534,7 @@ App::post('/v1/databases') } $queueForEvents->setParam('databaseId', $database->getId()); - $queueForUsage->addMetric(str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_STORAGE), 1); // per database + $queueForStatsUsage->addMetric(str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_STORAGE), 1); // per database $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -523,13 +546,19 @@ App::get('/v1/databases') ->groups(['api', 'database']) ->label('scope', 'databases.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'list') - ->label('sdk.description', '/docs/references/databases/list.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DATABASE_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'list', + description: '/docs/references/databases/list.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DATABASE_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('queries', [], new Databases(), '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(', ', Databases::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -579,13 +608,19 @@ App::get('/v1/databases/:databaseId') ->groups(['api', 'database']) ->label('scope', 'databases.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/databases/get.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DATABASE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'get', + description: '/docs/references/databases/get.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DATABASE, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->inject('response') ->inject('dbForProject') @@ -605,13 +640,19 @@ App::get('/v1/databases/:databaseId/logs') ->groups(['api', 'database']) ->label('scope', 'databases.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listLogs') - ->label('sdk.description', '/docs/references/databases/get-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listLogs', + description: '/docs/references/databases/get-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), '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', true) ->inject('response') @@ -632,13 +673,15 @@ App::get('/v1/databases/:databaseId/logs') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $grouped = Query::groupByType($queries); - $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; - $offset = $grouped['offset'] ?? 0; + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); $audit = new Audit($dbForProject); $resource = 'database/' . $databaseId; - $logs = $audit->getLogsByResource($resource, $limit, $offset); + $logs = $audit->getLogsByResource($resource, $queries); $output = []; @@ -686,7 +729,7 @@ App::get('/v1/databases/:databaseId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource), + 'total' => $audit->countLogsByResource($resource, $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -700,13 +743,19 @@ App::put('/v1/databases/:databaseId') ->label('event', 'databases.[databaseId].update') ->label('audits.event', 'database.update') ->label('audits.resource', 'database/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'update') - ->label('sdk.description', '/docs/references/databases/update.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DATABASE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'update', + description: '/docs/references/databases/update.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DATABASE, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('name', null, new Text(128), 'Database name. Max length: 128 chars.') ->param('enabled', true, new Boolean(), '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.', true) @@ -739,19 +788,26 @@ App::delete('/v1/databases/:databaseId') ->label('event', 'databases.[databaseId].delete') ->label('audits.event', 'database.delete') ->label('audits.resource', 'database/{request.databaseId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/databases/delete.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'delete', + description: '/docs/references/databases/delete.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('databaseId', '', new UID(), 'Database ID.') ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('queueForUsage') - ->action(function (string $databaseId, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Usage $queueForUsage) { + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, StatsUsage $queueForStatsUsage) { $database = $dbForProject->getDocument('databases', $databaseId); @@ -774,7 +830,7 @@ App::delete('/v1/databases/:databaseId') ->setParam('databaseId', $database->getId()) ->setPayload($response->output($database, Response::MODEL_DATABASE)); - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_DATABASES_STORAGE, 1); // Global, deletion forces full recalculation $response->noContent(); @@ -788,13 +844,19 @@ App::post('/v1/databases/:databaseId/collections') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'collection.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'createCollection') - ->label('sdk.description', '/docs/references/databases/create-collection.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COLLECTION) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createCollection', + description: '/docs/references/databases/create-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_COLLECTION, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.') @@ -853,13 +915,19 @@ App::get('/v1/databases/:databaseId/collections') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listCollections') - ->label('sdk.description', '/docs/references/databases/list-collections.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COLLECTION_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listCollections', + description: '/docs/references/databases/list-collections.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_COLLECTION_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('queries', [], new Collections(), '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(', ', Collections::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) @@ -919,13 +987,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getCollection') - ->label('sdk.description', '/docs/references/databases/get-collection.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COLLECTION) + ->label('sdk', new Method( + namespace: 'databases', + name: 'getCollection', + description: '/docs/references/databases/get-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_COLLECTION, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') @@ -954,13 +1028,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listCollectionLogs') - ->label('sdk.description', '/docs/references/databases/get-collection-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listCollectionLogs', + description: '/docs/references/databases/get-collection-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), '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', true) @@ -983,14 +1063,21 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $queries = Query::parseQueries($queries); - $grouped = Query::groupByType($queries); - $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; - $offset = $grouped['offset'] ?? 0; + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); $audit = new Audit($dbForProject); $resource = 'database/' . $databaseId . '/collection/' . $collectionId; - $logs = $audit->getLogsByResource($resource, $limit, $offset); + $logs = $audit->getLogsByResource($resource, $queries); $output = []; @@ -1038,7 +1125,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource), + 'total' => $audit->countLogsByResource($resource, $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -1053,13 +1140,19 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->label('event', 'databases.[databaseId].collections.[collectionId].update') ->label('audits.event', 'collection.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateCollection') - ->label('sdk.description', '/docs/references/databases/update-collection.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COLLECTION) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateCollection', + description: '/docs/references/databases/update-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_COLLECTION, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('name', null, new Text(128), 'Collection name. Max length: 128 chars.') @@ -1121,12 +1214,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') ->label('event', 'databases.[databaseId].collections.[collectionId].delete') ->label('audits.event', 'collection.delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'deleteCollection') - ->label('sdk.description', '/docs/references/databases/delete-collection.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'deleteCollection', + description: '/docs/references/databases/delete-collection.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->inject('response') @@ -1177,13 +1277,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'createStringAttribute') - ->label('sdk.description', '/docs/references/databases/create-string-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_STRING) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createStringAttribute', + description: '/docs/references/databases/create-string-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_STRING + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1234,13 +1339,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email' ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createEmailAttribute') - ->label('sdk.description', '/docs/references/databases/create-email-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_EMAIL) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createEmailAttribute', + description: '/docs/references/databases/create-email-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_EMAIL, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1277,13 +1387,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createEnumAttribute') - ->label('sdk.description', '/docs/references/databases/create-attribute-enum.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_ENUM) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createEnumAttribute', + description: '/docs/references/databases/create-attribute-enum.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_ENUM, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1325,13 +1440,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createIpAttribute') - ->label('sdk.description', '/docs/references/databases/create-ip-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_IP) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createIpAttribute', + description: '/docs/references/databases/create-ip-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_IP, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1368,13 +1488,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createUrlAttribute') - ->label('sdk.description', '/docs/references/databases/create-url-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_URL) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createUrlAttribute', + description: '/docs/references/databases/create-url-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_URL, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1411,13 +1536,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createIntegerAttribute') - ->label('sdk.description', '/docs/references/databases/create-integer-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_INTEGER) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createIntegerAttribute', + description: '/docs/references/databases/create-integer-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_INTEGER, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1433,8 +1563,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { // Ensure attribute default is within range - $min = \is_null($min) ? PHP_INT_MIN : $min; - $max = \is_null($max) ? PHP_INT_MAX : $max; + $min ??= PHP_INT_MIN; + $max ??= PHP_INT_MAX; if ($min > $max) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); @@ -1483,13 +1613,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createFloatAttribute') - ->label('sdk.description', '/docs/references/databases/create-float-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_FLOAT) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createFloatAttribute', + description: '/docs/references/databases/create-float-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_FLOAT, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1505,8 +1640,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { // Ensure attribute default is within range - $min = \is_null($min) ? -PHP_FLOAT_MAX : $min; - $max = \is_null($max) ? PHP_FLOAT_MAX : $max; + $min ??= -PHP_FLOAT_MAX; + $max ??= PHP_FLOAT_MAX; if ($min > $max) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); @@ -1553,13 +1688,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createBooleanAttribute') - ->label('sdk.description', '/docs/references/databases/create-boolean-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_BOOLEAN) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createBooleanAttribute', + description: '/docs/references/databases/create-boolean-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_BOOLEAN, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1595,13 +1735,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/dateti ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createDatetimeAttribute') - ->label('sdk.description', '/docs/references/databases/create-datetime-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_DATETIME) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createDatetimeAttribute', + description: '/docs/references/databases/create-datetime-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_DATETIME, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1640,13 +1785,18 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'attribute.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.namespace', 'databases') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.method', 'createRelationshipAttribute') - ->label('sdk.description', '/docs/references/databases/create-relationship-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_RELATIONSHIP) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createRelationshipAttribute', + description: '/docs/references/databases/create-relationship-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_ATTRIBUTE_RELATIONSHIP, + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('relatedCollectionId', '', new UID(), 'Related Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') @@ -1766,13 +1916,18 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listAttributes') - ->label('sdk.description', '/docs/references/databases/list-attributes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listAttributes', + description: '/docs/references/databases/list-attributes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_LIST + ) + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('queries', [], new Attributes(), '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(', ', Attributes::ALLOWED_ATTRIBUTES), true) @@ -1847,23 +2002,29 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getAttribute') - ->label('sdk.description', '/docs/references/databases/get-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', [ - Response::MODEL_ATTRIBUTE_BOOLEAN, - Response::MODEL_ATTRIBUTE_INTEGER, - Response::MODEL_ATTRIBUTE_FLOAT, - Response::MODEL_ATTRIBUTE_EMAIL, - Response::MODEL_ATTRIBUTE_ENUM, - Response::MODEL_ATTRIBUTE_URL, - Response::MODEL_ATTRIBUTE_IP, - Response::MODEL_ATTRIBUTE_DATETIME, - Response::MODEL_ATTRIBUTE_RELATIONSHIP, - Response::MODEL_ATTRIBUTE_STRING])// needs to be last, since its condition would dominate any other string attribute + ->label('sdk', new Method( + namespace: 'databases', + name: 'getAttribute', + description: '/docs/references/databases/get-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: [ + Response::MODEL_ATTRIBUTE_BOOLEAN, + Response::MODEL_ATTRIBUTE_INTEGER, + Response::MODEL_ATTRIBUTE_FLOAT, + Response::MODEL_ATTRIBUTE_EMAIL, + Response::MODEL_ATTRIBUTE_ENUM, + Response::MODEL_ATTRIBUTE_URL, + Response::MODEL_ATTRIBUTE_IP, + Response::MODEL_ATTRIBUTE_DATETIME, + Response::MODEL_ATTRIBUTE_RELATIONSHIP, + Response::MODEL_ATTRIBUTE_STRING + ] + ), + ] + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1925,12 +2086,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/strin ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateStringAttribute') - ->label('sdk.description', '/docs/references/databases/update-string-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_STRING) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateStringAttribute', + description: '/docs/references/databases/update-string-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_STRING, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -1969,12 +2137,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/email ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateEmailAttribute') - ->label('sdk.description', '/docs/references/databases/update-email-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_EMAIL) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateEmailAttribute', + description: '/docs/references/databases/update-email-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_EMAIL, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2011,12 +2186,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/enum/ ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateEnumAttribute') - ->label('sdk.description', '/docs/references/databases/update-enum-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_ENUM) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateEnumAttribute', + description: '/docs/references/databases/update-enum-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_ENUM, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2055,12 +2237,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/ip/:k ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateIpAttribute') - ->label('sdk.description', '/docs/references/databases/update-ip-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_IP) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateIpAttribute', + description: '/docs/references/databases/update-ip-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_IP, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2097,12 +2286,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/url/: ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateUrlAttribute') - ->label('sdk.description', '/docs/references/databases/update-url-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_URL) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateUrlAttribute', + description: '/docs/references/databases/update-url-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_URL, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2139,18 +2335,25 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/integ ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateIntegerAttribute') - ->label('sdk.description', '/docs/references/databases/update-integer-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_INTEGER) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateIntegerAttribute', + description: '/docs/references/databases/update-integer-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_INTEGER, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('min', null, new Integer(), 'Minimum value to enforce on new documents') - ->param('max', null, new Integer(), 'Maximum value to enforce on new documents') + ->param('min', null, new Integer(), 'Minimum value to enforce on new documents', true) + ->param('max', null, new Integer(), 'Maximum value to enforce on new documents', true) ->param('default', null, new Nullable(new Integer()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') ->param('newKey', null, new Key(), 'New attribute key.', true) ->inject('response') @@ -2191,18 +2394,25 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/float ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateFloatAttribute') - ->label('sdk.description', '/docs/references/databases/update-float-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_FLOAT) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateFloatAttribute', + description: '/docs/references/databases/update-float-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_FLOAT, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') ->param('required', null, new Boolean(), 'Is attribute required?') - ->param('min', null, new FloatValidator(), 'Minimum value to enforce on new documents') - ->param('max', null, new FloatValidator(), 'Maximum value to enforce on new documents') + ->param('min', null, new FloatValidator(), 'Minimum value to enforce on new documents', true) + ->param('max', null, new FloatValidator(), 'Maximum value to enforce on new documents', true) ->param('default', null, new Nullable(new FloatValidator()), 'Default value for attribute when not provided. Cannot be set when attribute is required.') ->param('newKey', null, new Key(), 'New attribute key.', true) ->inject('response') @@ -2243,12 +2453,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/boole ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateBooleanAttribute') - ->label('sdk.description', '/docs/references/databases/update-boolean-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_BOOLEAN) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateBooleanAttribute', + description: '/docs/references/databases/update-boolean-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_BOOLEAN, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2284,12 +2501,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/datet ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateDatetimeAttribute') - ->label('sdk.description', '/docs/references/databases/update-datetime-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_DATETIME) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateDatetimeAttribute', + description: '/docs/references/databases/update-datetime-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_DATETIME, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2325,12 +2549,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/ ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.update') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateRelationshipAttribute') - ->label('sdk.description', '/docs/references/databases/update-relationship-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_RELATIONSHIP) + ->label('sdk', new Method( + namespace: 'databases', + name: 'updateRelationshipAttribute', + description: '/docs/references/databases/update-relationship-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ATTRIBUTE_RELATIONSHIP, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2383,12 +2614,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].update') ->label('audits.event', 'attribute.delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'deleteAttribute') - ->label('sdk.description', '/docs/references/databases/delete-attribute.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'deleteAttribute', + description: '/docs/references/databases/delete-attribute.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') @@ -2396,8 +2634,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('queueForUsage') - ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, Usage $queueForUsage) { + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, string $collectionId, string $key, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, StatsUsage $queueForStatsUsage) { $db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); @@ -2416,6 +2654,18 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } + /** + * Check index dependency + */ + $validator = new IndexDependencyValidator( + $collection->getAttribute('indexes'), + $dbForProject->getAdapter()->getSupportForCastIndexArray(), + ); + + if (! $validator->isValid($attribute)) { + throw new Exception(Exception::INDEX_DEPENDENCY); + } + // Only update status if removing available attribute if ($attribute->getAttribute('status') === 'available') { $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); @@ -2482,7 +2732,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key ->setContext('database', $db) ->setPayload($response->output($attribute, $model)); - $queueForUsage + $queueForStatsUsage ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$db->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection $response->noContent(); @@ -2497,13 +2747,19 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'index.create') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'createIndex') - ->label('sdk.description', '/docs/references/databases/create-index.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_INDEX) + ->label('sdk', new Method( + namespace: 'databases', + name: 'createIndex', + description: '/docs/references/databases/create-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_INDEX, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', null, new Key(), 'Index Key.') @@ -2582,12 +2838,11 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key')); if ($attributeIndex === false) { - throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown attribute: ' . $attribute); + throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown attribute: ' . $attribute . '. Verify the attribute name or create the attribute.'); } $attributeStatus = $oldAttributes[$attributeIndex]['status']; $attributeType = $oldAttributes[$attributeIndex]['type']; - $attributeSize = $oldAttributes[$attributeIndex]['size']; $attributeArray = $oldAttributes[$attributeIndex]['array'] ?? false; if ($attributeType === Database::VAR_RELATIONSHIP) { @@ -2601,10 +2856,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $lengths[$i] = null; - if ($attributeType === Database::VAR_STRING) { - $lengths[$i] = $attributeSize; // set attribute size as index length only for strings - } - if ($attributeArray === true) { $lengths[$i] = Database::ARRAY_INDEX_LENGTH; $orders[$i] = null; @@ -2627,7 +2878,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $validator = new IndexValidator( $collection->getAttribute('attributes'), - $dbForProject->getAdapter()->getMaxIndexLength() + $dbForProject->getAdapter()->getMaxIndexLength(), + $dbForProject->getAdapter()->getInternalIndexesKeys(), ); if (!$validator->isValid($index)) { throw new Exception(Exception::INDEX_INVALID, $validator->getDescription()); @@ -2665,13 +2917,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listIndexes') - ->label('sdk.description', '/docs/references/databases/list-indexes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_INDEX_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listIndexes', + description: '/docs/references/databases/list-indexes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_INDEX_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('queries', [], new Indexes(), '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(', ', Indexes::ALLOWED_ATTRIBUTES), true) @@ -2741,13 +2999,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->groups(['api', 'database']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getIndex') - ->label('sdk.description', '/docs/references/databases/get-index.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_INDEX) + ->label('sdk', new Method( + namespace: 'databases', + name: 'getIndex', + description: '/docs/references/databases/get-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_INDEX, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', null, new Key(), 'Index Key.') @@ -2784,12 +3048,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update') ->label('audits.event', 'index.delete') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'deleteIndex') - ->label('sdk.description', '/docs/references/databases/delete-index.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'deleteIndex', + description: '/docs/references/databases/delete-index.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Index Key.') @@ -2852,15 +3123,24 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->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.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'createDocument') - ->label('sdk.description', '/docs/references/databases/create-document.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DOCUMENT) - ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') - ->label('sdk.offline.key', '{documentId}') + ->label( + 'sdk', + [ + new Method( + namespace: 'databases', + name: 'createDocument', + description: '/docs/references/databases/create-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_DOCUMENT, + ) + ], + contentType: ContentType::JSON + ) + ] + ) ->param('databaseId', '', new UID(), 'Database ID.') ->param('documentId', '', new CustomId(), '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.') ->param('collectionId', '', new UID(), '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.') @@ -2870,9 +3150,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->inject('dbForProject') ->inject('user') ->inject('queueForEvents') - ->inject('queueForUsage') - ->inject('mode') - ->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, Usage $queueForUsage, string $mode) { + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, string $documentId, string $collectionId, string|array $data, ?array $permissions, Response $response, Database $dbForProject, Document $user, Event $queueForEvents, StatsUsage $queueForStatsUsage) { $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array @@ -2943,7 +3222,11 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $data['$permissions'] = $permissions; $document = new Document($data); - $checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database) { + $operations = 0; + + $checkPermissions = function (Document $collection, Document $document, string $permission) use (&$checkPermissions, $dbForProject, $database, &$operations) { + $operations++; + $documentSecurity = $collection->getAttribute('documentSecurity', false); $validator = new Authorization($permission); @@ -3035,6 +3318,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::COLLECTION_NOT_FOUND); } + // Add $collectionId and $databaseId for all documents $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { $document->setAttribute('$databaseId', $database->getId()); @@ -3070,6 +3354,13 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $processDocument($collection, $document); + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations) + ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection + + $response->addHeader('X-Debug-Operations', $operations); + $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($document, Response::MODEL_DOCUMENT); @@ -3089,10 +3380,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') ->setContext('collection', $collection) ->setContext('database', $database) ->setPayload($response->getPayload(), sensitive: $relationships); - - - $queueForUsage - ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection }); App::get('/v1/databases/:databaseId/collections/:collectionId/documents') @@ -3101,21 +3388,26 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') ->groups(['api', 'database']) ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listDocuments') - ->label('sdk.description', '/docs/references/databases/list-documents.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DOCUMENT_LIST) - ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') + ->label('sdk', new Method( + namespace: 'databases', + name: 'listDocuments', + description: '/docs/references/databases/list-documents.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DOCUMENT_LIST, + ) + ], + contentType: ContentType::JSON + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), '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.', true) ->inject('response') ->inject('dbForProject') - ->inject('mode') - ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, string $mode) { + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3151,7 +3443,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); } - $documentId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); @@ -3166,12 +3457,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); + $operations = 0; + // Add $collectionId and $databaseId for all documents - $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool { + $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations): bool { if ($document->isEmpty()) { return false; } + $operations++; + $document->removeAttribute('$collection'); $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3185,8 +3480,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $related = $document->getAttribute($relationship->getAttribute('key')); if (empty($related)) { + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + continue; } + if (!\is_array($related)) { $relations = [$related]; } else { @@ -3194,6 +3494,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)); foreach ($relations as $index => $doc) { @@ -3218,6 +3519,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $processDocument($collection, $document); } + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); + + $response->addHeader('X-Debug-Operations', $operations); + $select = \array_reduce($queries, function ($result, $query) { return $result || ($query->getMethod() === Query::TYPE_SELECT); }, false); @@ -3257,25 +3564,28 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->groups(['api', 'database']) ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getDocument') - ->label('sdk.description', '/docs/references/databases/get-document.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DOCUMENT) - ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') - ->label('sdk.offline.key', '{documentId}') + ->label('sdk', new Method( + namespace: 'databases', + name: 'getDocument', + description: '/docs/references/databases/get-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. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('documentId', '', new UID(), 'Document ID.') ->param('queries', [], new ArrayList(new Text(APP_LIMIT_ARRAY_ELEMENT_SIZE), APP_LIMIT_ARRAY_PARAMS_SIZE), '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.', true) ->inject('response') ->inject('dbForProject') - ->inject('mode') - ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, string $mode) { + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, StatsUsage $queueForStatsUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -3302,12 +3612,16 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DOCUMENT_NOT_FOUND); } + $operations = 0; + // Add $collectionId and $databaseId for all documents - $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database, &$operations) { if ($document->isEmpty()) { return; } + $operations++; + $document->setAttribute('$databaseId', $database->getId()); $document->setAttribute('$collectionId', $collection->getId()); @@ -3320,8 +3634,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $related = $document->getAttribute($relationship->getAttribute('key')); if (empty($related)) { + if (\in_array(\gettype($related), ['array', 'object'])) { + $operations++; + } + continue; } + if (!\is_array($related)) { $related = [$related]; } @@ -3341,6 +3660,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $processDocument($collection, $document); + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_READS, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), $operations); + + $response->addHeader('X-Debug-Operations', $operations); + $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -3350,13 +3675,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->groups(['api', 'database']) ->label('scope', 'documents.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'listDocumentLogs') - ->label('sdk.description', '/docs/references/databases/get-document-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'databases', + name: 'listDocumentLogs', + description: '/docs/references/databases/get-document-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ], + contentType: ContentType::JSON, + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('documentId', '', new UID(), 'Document ID.') @@ -3391,13 +3722,15 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $grouped = Query::groupByType($queries); - $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; - $offset = $grouped['offset'] ?? 0; + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); $audit = new Audit($dbForProject); $resource = 'database/' . $databaseId . '/collection/' . $collectionId . '/document/' . $document->getId(); - $logs = $audit->getLogsByResource($resource, $limit, $offset); + $logs = $audit->getLogsByResource($resource, $queries); $output = []; @@ -3443,8 +3776,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $output[$i]['countryName'] = $locale->getText('locale.country.unknown'); } } + $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource), + 'total' => $audit->countLogsByResource($resource, $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -3461,15 +3795,19 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->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.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'updateDocument') - ->label('sdk.description', '/docs/references/databases/update-document.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DOCUMENT) - ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') - ->label('sdk.offline.key', '{documentId}') + ->label('sdk', new Method( + namespace: 'databases', + 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.') @@ -3479,8 +3817,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('mode') - ->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, string $mode) { + ->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 @@ -3547,7 +3885,12 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $data['$permissions'] = $permissions; $newDocument = new Document($data); - $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database) { + $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 @@ -3615,6 +3958,12 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $setCollection($collection, $newDocument); + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, max($operations, 1)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), $operations); + + $response->addHeader('X-Debug-Operations', $operations); + try { $document = $dbForProject->withRequestTimestamp( $requestTimestamp, @@ -3700,14 +4049,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'deleteDocument') - ->label('sdk.description', '/docs/references/databases/delete-document.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) - ->label('sdk.offline.model', '/databases/{databaseId}/collections/{collectionId}/documents') - ->label('sdk.offline.key', '{documentId}') + ->label('sdk', new Method( + namespace: 'databases', + name: 'deleteDocument', + description: '/docs/references/databases/delete-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('documentId', '', new UID(), 'Document ID.') @@ -3715,9 +4069,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->inject('queueForUsage') - ->inject('mode') - ->action(function (string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, Usage $queueForUsage, string $mode) { + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, string $collectionId, string $documentId, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); @@ -3786,6 +4139,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $processDocument($collection, $document); + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1) + ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection + + $response->addHeader('X-Debug-Operations', 1); + $relationships = \array_map( fn ($document) => $document->getAttribute('key'), \array_filter( @@ -3802,9 +4162,6 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu ->setContext('database', $database) ->setPayload($response->output($document, Response::MODEL_DOCUMENT), sensitive: $relationships); - $queueForUsage - ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE), 1); // per collection - $response->noContent(); }); @@ -3813,12 +4170,19 @@ App::get('/v1/databases/usage') ->groups(['api', 'database', 'usage']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_DATABASES) + ->label('sdk', new Method( + namespace: 'databases', + name: 'getUsage', + description: '/docs/references/databases/get-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_DATABASES, + ) + ], + contentType: ContentType::JSON + )) ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), '`Date range.', true) ->inject('response') ->inject('dbForProject') @@ -3831,7 +4195,9 @@ App::get('/v1/databases/usage') METRIC_DATABASES, METRIC_COLLECTIONS, METRIC_DOCUMENTS, - METRIC_DATABASES_STORAGE + METRIC_DATABASES_STORAGE, + METRIC_DATABASES_OPERATIONS_READS, + METRIC_DATABASES_OPERATIONS_WRITES, ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -3883,10 +4249,14 @@ App::get('/v1/databases/usage') 'collectionsTotal' => $usage[$metrics[1]]['total'], 'documentsTotal' => $usage[$metrics[2]]['total'], 'storageTotal' => $usage[$metrics[3]]['total'], + 'databasesReadsTotal' => $usage[$metrics[4]]['total'], + 'databasesWritesTotal' => $usage[$metrics[5]]['total'], 'databases' => $usage[$metrics[0]]['data'], 'collections' => $usage[$metrics[1]]['data'], 'documents' => $usage[$metrics[2]]['data'], 'storage' => $usage[$metrics[3]]['data'], + 'databasesReads' => $usage[$metrics[4]]['data'], + 'databasesWrites' => $usage[$metrics[5]]['data'], ]), Response::MODEL_USAGE_DATABASES); }); @@ -3895,12 +4265,19 @@ App::get('/v1/databases/:databaseId/usage') ->groups(['api', 'database', 'usage']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getDatabaseUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_DATABASE) + ->label('sdk', new Method( + namespace: 'databases', + name: 'getDatabaseUsage', + description: '/docs/references/databases/get-database-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_DATABASE, + ) + ], + contentType: ContentType::JSON, + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), '`Date range.', true) ->inject('response') @@ -3919,7 +4296,9 @@ App::get('/v1/databases/:databaseId/usage') $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_STORAGE), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_READS), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASES_OPERATIONS_WRITES) ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -3971,9 +4350,13 @@ App::get('/v1/databases/:databaseId/usage') 'collectionsTotal' => $usage[$metrics[0]]['total'], 'documentsTotal' => $usage[$metrics[1]]['total'], 'storageTotal' => $usage[$metrics[2]]['total'], + 'databaseReadsTotal' => $usage[$metrics[3]]['total'], + 'databaseWritesTotal' => $usage[$metrics[4]]['total'], 'collections' => $usage[$metrics[0]]['data'], 'documents' => $usage[$metrics[1]]['data'], 'storage' => $usage[$metrics[2]]['data'], + 'databaseReads' => $usage[$metrics[3]]['data'], + 'databaseWrites' => $usage[$metrics[4]]['data'], ]), Response::MODEL_USAGE_DATABASE); }); @@ -3983,12 +4366,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') ->groups(['api', 'database', 'usage']) ->label('scope', 'collections.read') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getCollectionUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_COLLECTION) + ->label('sdk', new Method( + namespace: 'databases', + name: 'getCollectionUsage', + description: '/docs/references/databases/get-collection-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_COLLECTION, + ) + ], + contentType: ContentType::JSON, + )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->param('collectionId', '', new UID(), 'Collection ID.') diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php deleted file mode 100644 index 287c5fa80b..0000000000 --- a/app/controllers/api/functions.php +++ /dev/null @@ -1,2658 +0,0 @@ -<?php - -use Ahc\Jwt\JWT; -use Appwrite\Auth\Auth; -use Appwrite\Event\Build; -use Appwrite\Event\Delete; -use Appwrite\Event\Event; -use Appwrite\Event\Func; -use Appwrite\Event\Usage; -use Appwrite\Event\Validator\FunctionEvent; -use Appwrite\Extend\Exception; -use Appwrite\Extend\Exception as AppwriteException; -use Appwrite\Functions\Validator\Headers; -use Appwrite\Functions\Validator\RuntimeSpecification; -use Appwrite\Messaging\Adapter\Realtime; -use Appwrite\Platform\Tasks\ScheduleExecutions; -use Appwrite\Task\Validator\Cron; -use Appwrite\Utopia\Database\Validator\CustomId; -use Appwrite\Utopia\Database\Validator\Queries\Deployments; -use Appwrite\Utopia\Database\Validator\Queries\Executions; -use Appwrite\Utopia\Database\Validator\Queries\Functions; -use Appwrite\Utopia\Response; -use Appwrite\Utopia\Response\Model\Rule; -use Executor\Executor; -use MaxMind\Db\Reader; -use Utopia\App; -use Utopia\CLI\Console; -use Utopia\Config\Config; -use Utopia\Database\Database; -use Utopia\Database\DateTime; -use Utopia\Database\Document; -use Utopia\Database\Exception\Duplicate as DuplicateException; -use Utopia\Database\Exception\Query as QueryException; -use Utopia\Database\Helpers\ID; -use Utopia\Database\Helpers\Permission; -use Utopia\Database\Helpers\Role; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Datetime as DatetimeValidator; -use Utopia\Database\Validator\Query\Cursor; -use Utopia\Database\Validator\Roles; -use Utopia\Database\Validator\UID; -use Utopia\Storage\Device; -use Utopia\Storage\Validator\File; -use Utopia\Storage\Validator\FileExt; -use Utopia\Storage\Validator\FileSize; -use Utopia\Storage\Validator\Upload; -use Utopia\Swoole\Request; -use Utopia\System\System; -use Utopia\Validator\AnyOf; -use Utopia\Validator\ArrayList; -use Utopia\Validator\Assoc; -use Utopia\Validator\Boolean; -use Utopia\Validator\Nullable; -use Utopia\Validator\Range; -use Utopia\Validator\Text; -use Utopia\Validator\WhiteList; -use Utopia\VCS\Adapter\Git\GitHub; -use Utopia\VCS\Exception\RepositoryNotFound; - -include_once __DIR__ . '/../shared/api.php'; - -$redeployVcs = function (Request $request, Document $function, Document $project, Document $installation, Database $dbForProject, Build $queueForBuilds, Document $template, GitHub $github) { - $deploymentId = ID::unique(); - $entrypoint = $function->getAttribute('entrypoint', ''); - $providerInstallationId = $installation->getAttribute('providerInstallationId', ''); - $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); - $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); - $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); - $owner = $github->getOwnerName($providerInstallationId); - $providerRepositoryId = $function->getAttribute('providerRepositoryId', ''); - try { - $repositoryName = $github->getRepositoryName($providerRepositoryId) ?? ''; - if (empty($repositoryName)) { - throw new Exception(Exception::PROVIDER_REPOSITORY_NOT_FOUND); - } - } catch (RepositoryNotFound $e) { - throw new Exception(Exception::PROVIDER_REPOSITORY_NOT_FOUND); - } - $providerBranch = $function->getAttribute('providerBranch', 'main'); - $authorUrl = "https://github.com/$owner"; - $repositoryUrl = "https://github.com/$owner/$repositoryName"; - $branchUrl = "https://github.com/$owner/$repositoryName/tree/$providerBranch"; - - $commitDetails = []; - if ($template->isEmpty()) { - try { - $commitDetails = $github->getLatestCommit($owner, $repositoryName, $providerBranch); - } catch (\Throwable $error) { - Console::warning('Failed to get latest commit details'); - Console::warning($error->getMessage()); - Console::warning($error->getTraceAsString()); - } - } - - $deployment = $dbForProject->createDocument('deployments', new Document([ - '$id' => $deploymentId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], - 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), - 'resourceType' => 'functions', - 'entrypoint' => $entrypoint, - 'commands' => $function->getAttribute('commands', ''), - 'type' => 'vcs', - 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), - 'providerRepositoryId' => $providerRepositoryId, - 'repositoryId' => $function->getAttribute('repositoryId', ''), - 'repositoryInternalId' => $function->getAttribute('repositoryInternalId', ''), - 'providerBranchUrl' => $branchUrl, - 'providerRepositoryName' => $repositoryName, - 'providerRepositoryOwner' => $owner, - 'providerRepositoryUrl' => $repositoryUrl, - 'providerCommitHash' => $commitDetails['commitHash'] ?? '', - 'providerCommitAuthorUrl' => $authorUrl, - 'providerCommitAuthor' => $commitDetails['commitAuthor'] ?? '', - 'providerCommitMessage' => $commitDetails['commitMessage'] ?? '', - 'providerCommitUrl' => $commitDetails['commitUrl'] ?? '', - 'providerBranch' => $providerBranch, - 'providerRootDirectory' => $function->getAttribute('providerRootDirectory', ''), - 'search' => implode(' ', [$deploymentId, $entrypoint]), - 'activate' => true, - ])); - - $queueForBuilds - ->setType(BUILD_TYPE_DEPLOYMENT) - ->setResource($function) - ->setDeployment($deployment) - ->setTemplate($template); -}; - -App::post('/v1/functions') - ->groups(['api', 'functions']) - ->desc('Create function') - ->label('scope', 'functions.write') - ->label('event', 'functions.[functionId].create') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('audits.event', 'function.create') - ->label('audits.resource', 'function/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'create') - ->label('sdk.description', '/docs/references/functions/create-function.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FUNCTION) - ->param('functionId', '', new CustomId(), '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.') - ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') - ->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.') - ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), '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 ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) - ->param('events', [], new ArrayList(new FunctionEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true) - ->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true) - ->param('timeout', 15, new Range(1, (int) System::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Function maximum execution time in seconds.', true) - ->param('enabled', true, new Boolean(), '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.', true) - ->param('logging', true, new Boolean(), 'Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.', true) - ->param('entrypoint', '', new Text(1028, 0), 'Entrypoint File. This path is relative to the "providerRootDirectory".', true) - ->param('commands', '', new Text(8192, 0), 'Build Commands.', true) - ->param('scopes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of scopes allowed for API key auto-generated for every execution. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.', true) - ->param('installationId', '', new Text(128, 0), 'Appwrite Installation ID for VCS (Version Control System) deployment.', true) - ->param('providerRepositoryId', '', new Text(128, 0), 'Repository ID of the repo linked to the function.', true) - ->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the function.', true) - ->param('providerSilentMode', false, new Boolean(), '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.', true) - ->param('providerRootDirectory', '', new Text(128, 0), 'Path to function code in the linked repo.', true) - ->param('templateRepository', '', new Text(128, 0), 'Repository name of the template.', true) - ->param('templateOwner', '', new Text(128, 0), 'The name of the owner of the template.', true) - ->param('templateRootDirectory', '', new Text(128, 0), 'Path to function code in the template repo.', true) - ->param('templateVersion', '', new Text(128, 0), 'Version (tag) for the repo linked to the function template.', true) - ->param('specification', APP_FUNCTION_SPECIFICATION_DEFAULT, fn (array $plan) => new RuntimeSpecification( - $plan, - Config::getParam('runtime-specifications', []), - App::getEnv('_APP_FUNCTIONS_CPUS', APP_FUNCTION_CPUS_DEFAULT), - App::getEnv('_APP_FUNCTIONS_MEMORY', APP_FUNCTION_MEMORY_DEFAULT) - ), 'Runtime specification for the function and builds.', true, ['plan']) - ->inject('request') - ->inject('response') - ->inject('dbForProject') - ->inject('project') - ->inject('user') - ->inject('queueForEvents') - ->inject('queueForBuilds') - ->inject('dbForConsole') - ->inject('gitHub') - ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github) use ($redeployVcs) { - $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; - - $allowList = \array_filter(\explode(',', System::getEnv('_APP_FUNCTIONS_RUNTIMES', ''))); - - if (!empty($allowList) && !\in_array($runtime, $allowList)) { - throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $runtime . '" is not supported'); - } - - // build from template - $template = new Document([]); - if ( - !empty($templateRepository) - && !empty($templateOwner) - && !empty($templateRootDirectory) - && !empty($templateVersion) - ) { - $template->setAttribute('repositoryName', $templateRepository) - ->setAttribute('ownerName', $templateOwner) - ->setAttribute('rootDirectory', $templateRootDirectory) - ->setAttribute('version', $templateVersion); - } - - $installation = $dbForConsole->getDocument('installations', $installationId); - - if (!empty($installationId) && $installation->isEmpty()) { - throw new Exception(Exception::INSTALLATION_NOT_FOUND); - } - - if (!empty($providerRepositoryId) && (empty($installationId) || empty($providerBranch))) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'When connecting to VCS (Version Control System), you need to provide "installationId" and "providerBranch".'); - } - - $function = $dbForProject->createDocument('functions', new Document([ - '$id' => $functionId, - 'execute' => $execute, - 'enabled' => $enabled, - 'live' => true, - 'logging' => $logging, - 'name' => $name, - 'runtime' => $runtime, - 'deploymentInternalId' => '', - 'deployment' => '', - 'events' => $events, - 'schedule' => $schedule, - 'scheduleInternalId' => '', - 'scheduleId' => '', - 'timeout' => $timeout, - 'entrypoint' => $entrypoint, - 'commands' => $commands, - 'scopes' => $scopes, - 'search' => implode(' ', [$functionId, $name, $runtime]), - 'version' => 'v4', - 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), - 'providerRepositoryId' => $providerRepositoryId, - 'repositoryId' => '', - 'repositoryInternalId' => '', - 'providerBranch' => $providerBranch, - 'providerRootDirectory' => $providerRootDirectory, - 'providerSilentMode' => $providerSilentMode, - 'specification' => $specification - ])); - - $schedule = Authorization::skip( - fn () => $dbForConsole->createDocument('schedules', new Document([ - 'region' => System::getEnv('_APP_REGION', 'default'), // Todo replace with projects region - 'resourceType' => 'function', - 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), - 'resourceUpdatedAt' => DateTime::now(), - 'projectId' => $project->getId(), - 'schedule' => $function->getAttribute('schedule'), - 'active' => false, - ])) - ); - - $function->setAttribute('scheduleId', $schedule->getId()); - $function->setAttribute('scheduleInternalId', $schedule->getInternalId()); - - // Git connect logic - if (!empty($providerRepositoryId)) { - $teamId = $project->getAttribute('teamId', ''); - - $repository = $dbForConsole->createDocument('repositories', new Document([ - '$id' => ID::unique(), - '$permissions' => [ - Permission::read(Role::team(ID::custom($teamId))), - Permission::update(Role::team(ID::custom($teamId), 'owner')), - Permission::update(Role::team(ID::custom($teamId), 'developer')), - Permission::delete(Role::team(ID::custom($teamId), 'owner')), - Permission::delete(Role::team(ID::custom($teamId), 'developer')), - ], - 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), - 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), - 'providerRepositoryId' => $providerRepositoryId, - 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), - 'resourceType' => 'function', - 'providerPullRequestIds' => [] - ])); - - $function->setAttribute('repositoryId', $repository->getId()); - $function->setAttribute('repositoryInternalId', $repository->getInternalId()); - } - - $function = $dbForProject->updateDocument('functions', $function->getId(), $function); - - if (!empty($providerRepositoryId)) { - // Deploy VCS - $redeployVcs($request, $function, $project, $installation, $dbForProject, $queueForBuilds, $template, $github); - } elseif (!$template->isEmpty()) { - // Deploy non-VCS from template - $deploymentId = ID::unique(); - $deployment = $dbForProject->createDocument('deployments', new Document([ - '$id' => $deploymentId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], - 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), - 'resourceType' => 'functions', - 'entrypoint' => $function->getAttribute('entrypoint', ''), - 'commands' => $function->getAttribute('commands', ''), - 'type' => 'manual', - 'search' => implode(' ', [$deploymentId, $function->getAttribute('entrypoint', '')]), - 'activate' => true, - ])); - - $queueForBuilds - ->setType(BUILD_TYPE_DEPLOYMENT) - ->setResource($function) - ->setDeployment($deployment) - ->setTemplate($template); - } - - $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); - if (!empty($functionsDomain)) { - $routeSubdomain = ID::unique(); - $domain = "{$routeSubdomain}.{$functionsDomain}"; - $ruleId = md5($domain); - - $rule = Authorization::skip( - fn () => $dbForConsole->createDocument('rules', new Document([ - '$id' => $ruleId, - 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), - 'domain' => $domain, - 'resourceType' => 'function', - 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), - 'status' => 'verified', - 'certificateId' => '', - ])) - ); - - /** Trigger Webhook */ - $ruleModel = new Rule(); - $ruleCreate = - $queueForEvents - ->setClass(Event::WEBHOOK_CLASS_NAME) - ->setQueue(Event::WEBHOOK_QUEUE_NAME); - - $ruleCreate - ->setProject($project) - ->setEvent('rules.[ruleId].create') - ->setParam('ruleId', $rule->getId()) - ->setPayload($rule->getArrayCopy(array_keys($ruleModel->getRules()))) - ->trigger(); - - /** Trigger Functions */ - $ruleCreate - ->setClass(Event::FUNCTIONS_CLASS_NAME) - ->setQueue(Event::FUNCTIONS_QUEUE_NAME) - ->trigger(); - - /** Trigger realtime event */ - $allEvents = Event::generateEvents('rules.[ruleId].create', [ - 'ruleId' => $rule->getId(), - ]); - $target = Realtime::fromPayload( - // Pass first, most verbose event pattern - event: $allEvents[0], - payload: $rule, - project: $project - ); - Realtime::send( - projectId: 'console', - payload: $rule->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'] - ); - Realtime::send( - projectId: $project->getId(), - payload: $rule->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'] - ); - } - - $queueForEvents->setParam('functionId', $function->getId()); - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($function, Response::MODEL_FUNCTION); - }); - -App::get('/v1/functions') - ->groups(['api', 'functions']) - ->desc('List functions') - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'list') - ->label('sdk.description', '/docs/references/functions/list-functions.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FUNCTION_LIST) - ->param('queries', [], new Functions(), '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(', ', Functions::ALLOWED_ATTRIBUTES), true) - ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->inject('response') - ->inject('dbForProject') - ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - if (!empty($search)) { - $queries[] = Query::search('search', $search); - } - - /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ - $cursor = \array_filter($queries, function ($query) { - return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - }); - $cursor = reset($cursor); - if ($cursor) { - /** @var Query $cursor */ - - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $functionId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('functions', $functionId); - - if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Function '{$functionId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorDocument); - } - - $filterQueries = Query::groupByType($queries)['filters']; - - $response->dynamic(new Document([ - 'functions' => $dbForProject->find('functions', $queries), - 'total' => $dbForProject->count('functions', $filterQueries, APP_LIMIT_COUNT), - ]), Response::MODEL_FUNCTION_LIST); - }); - -App::get('/v1/functions/runtimes') - ->groups(['api', 'functions']) - ->desc('List runtimes') - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listRuntimes') - ->label('sdk.description', '/docs/references/functions/list-runtimes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_RUNTIME_LIST) - ->inject('response') - ->action(function (Response $response) { - $runtimes = Config::getParam('runtimes'); - - $allowList = \array_filter(\explode(',', System::getEnv('_APP_FUNCTIONS_RUNTIMES', ''))); - - $allowed = []; - foreach ($runtimes as $id => $runtime) { - if (!empty($allowList) && !\in_array($id, $allowList)) { - continue; - } - - $runtime['$id'] = $id; - $allowed[] = $runtime; - } - - $response->dynamic(new Document([ - 'total' => count($allowed), - 'runtimes' => $allowed - ]), Response::MODEL_RUNTIME_LIST); - }); - -App::get('/v1/functions/specifications') - ->groups(['api', 'functions']) - ->desc('List available function runtime specifications') - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listSpecifications') - ->label('sdk.description', '/docs/references/functions/list-specifications.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SPECIFICATION_LIST) - ->inject('response') - ->inject('plan') - ->action(function (Response $response, array $plan) { - $allRuntimeSpecs = Config::getParam('runtime-specifications', []); - - $runtimeSpecs = []; - foreach ($allRuntimeSpecs as $spec) { - $spec['enabled'] = true; - - if (array_key_exists('runtimeSpecifications', $plan)) { - $spec['enabled'] = in_array($spec['slug'], $plan['runtimeSpecifications']); - } - - // Only add specs that are within the limits set by environment variables - if ($spec['cpus'] <= System::getEnv('_APP_FUNCTIONS_CPUS', 1) && $spec['memory'] <= System::getEnv('_APP_FUNCTIONS_MEMORY', 512)) { - $runtimeSpecs[] = $spec; - } - } - - $response->dynamic(new Document([ - 'specifications' => $runtimeSpecs, - 'total' => count($runtimeSpecs) - ]), Response::MODEL_SPECIFICATION_LIST); - }); - -App::get('/v1/functions/:functionId') - ->groups(['api', 'functions']) - ->desc('Get function') - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/functions/get-function.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FUNCTION) - ->param('functionId', '', new UID(), 'Function ID.') - ->inject('response') - ->inject('dbForProject') - ->action(function (string $functionId, Response $response, Database $dbForProject) { - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $response->dynamic($function, Response::MODEL_FUNCTION); - }); - -App::get('/v1/functions/:functionId/usage') - ->desc('Get function usage') - ->groups(['api', 'functions', 'usage']) - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getFunctionUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_FUNCTION) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $functionId, string $range, Response $response, Database $dbForProject) { - - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $periods = Config::getParam('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) - ]; - - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { - foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', ['inf']) - ]); - - $stats[$metric]['total'] = $result['value'] ?? 0; - $limit = $days['limit']; - $period = $days['period']; - $results = $dbForProject->find('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', [$period]), - Query::limit($limit), - Query::orderDesc('time'), - ]); - $stats[$metric]['data'] = []; - foreach ($results as $result) { - $stats[$metric]['data'][$result->getAttribute('time')] = [ - 'value' => $result->getAttribute('value'), - ]; - } - } - }); - - $format = match ($days['period']) { - '1h' => 'Y-m-d\TH:00:00.000P', - '1d' => 'Y-m-d\T00:00:00.000P', - }; - - foreach ($metrics as $metric) { - $usage[$metric]['total'] = $stats[$metric]['total']; - $usage[$metric]['data'] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric]['data'][] = [ - 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } - } - - $response->dynamic(new Document([ - 'range' => $range, - 'deploymentsTotal' => $usage[$metrics[0]]['total'], - 'deploymentsStorageTotal' => $usage[$metrics[1]]['total'], - 'buildsTotal' => $usage[$metrics[2]]['total'], - 'buildsStorageTotal' => $usage[$metrics[3]]['total'], - 'buildsTimeTotal' => $usage[$metrics[4]]['total'], - 'executionsTotal' => $usage[$metrics[5]]['total'], - 'executionsTimeTotal' => $usage[$metrics[6]]['total'], - 'deployments' => $usage[$metrics[0]]['data'], - 'deploymentsStorage' => $usage[$metrics[1]]['data'], - 'builds' => $usage[$metrics[2]]['data'], - 'buildsStorage' => $usage[$metrics[3]]['data'], - 'buildsTime' => $usage[$metrics[4]]['data'], - 'executions' => $usage[$metrics[5]]['data'], - 'executionsTime' => $usage[$metrics[6]]['data'], - 'buildsMbSecondsTotal' => $usage[$metrics[7]]['total'], - 'buildsMbSeconds' => $usage[$metrics[7]]['data'], - 'executionsMbSeconds' => $usage[$metrics[8]]['data'], - 'executionsMbSecondsTotal' => $usage[$metrics[8]]['total'] - ]), Response::MODEL_USAGE_FUNCTION); - }); - -App::get('/v1/functions/usage') - ->desc('Get functions usage') - ->groups(['api', 'functions']) - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_FUNCTIONS) - ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $range, Response $response, Database $dbForProject) { - - $periods = Config::getParam('usage', []); - $stats = $usage = []; - $days = $periods[$range]; - $metrics = [ - METRIC_FUNCTIONS, - METRIC_DEPLOYMENTS, - METRIC_DEPLOYMENTS_STORAGE, - METRIC_BUILDS, - METRIC_BUILDS_STORAGE, - METRIC_BUILDS_COMPUTE, - METRIC_EXECUTIONS, - METRIC_EXECUTIONS_COMPUTE, - METRIC_BUILDS_MB_SECONDS, - METRIC_EXECUTIONS_MB_SECONDS, - ]; - - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { - foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', ['inf']) - ]); - - $stats[$metric]['total'] = $result['value'] ?? 0; - $limit = $days['limit']; - $period = $days['period']; - $results = $dbForProject->find('stats', [ - Query::equal('metric', [$metric]), - Query::equal('period', [$period]), - Query::limit($limit), - Query::orderDesc('time'), - ]); - $stats[$metric]['data'] = []; - foreach ($results as $result) { - $stats[$metric]['data'][$result->getAttribute('time')] = [ - 'value' => $result->getAttribute('value'), - ]; - } - } - }); - - $format = match ($days['period']) { - '1h' => 'Y-m-d\TH:00:00.000P', - '1d' => 'Y-m-d\T00:00:00.000P', - }; - - foreach ($metrics as $metric) { - $usage[$metric]['total'] = $stats[$metric]['total']; - $usage[$metric]['data'] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric]['data'][] = [ - 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } - } - $response->dynamic(new Document([ - 'range' => $range, - 'functionsTotal' => $usage[$metrics[0]]['total'], - 'deploymentsTotal' => $usage[$metrics[1]]['total'], - 'deploymentsStorageTotal' => $usage[$metrics[2]]['total'], - 'buildsTotal' => $usage[$metrics[3]]['total'], - 'buildsStorageTotal' => $usage[$metrics[4]]['total'], - 'buildsTimeTotal' => $usage[$metrics[5]]['total'], - 'executionsTotal' => $usage[$metrics[6]]['total'], - 'executionsTimeTotal' => $usage[$metrics[7]]['total'], - 'functions' => $usage[$metrics[0]]['data'], - 'deployments' => $usage[$metrics[1]]['data'], - 'deploymentsStorage' => $usage[$metrics[2]]['data'], - 'builds' => $usage[$metrics[3]]['data'], - 'buildsStorage' => $usage[$metrics[4]]['data'], - 'buildsTime' => $usage[$metrics[5]]['data'], - 'executions' => $usage[$metrics[6]]['data'], - 'executionsTime' => $usage[$metrics[7]]['data'], - 'buildsMbSecondsTotal' => $usage[$metrics[8]]['total'], - 'buildsMbSeconds' => $usage[$metrics[8]]['data'], - 'executionsMbSeconds' => $usage[$metrics[9]]['data'], - 'executionsMbSecondsTotal' => $usage[$metrics[9]]['total'], - ]), Response::MODEL_USAGE_FUNCTIONS); - }); - -App::put('/v1/functions/:functionId') - ->groups(['api', 'functions']) - ->desc('Update function') - ->label('scope', 'functions.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('event', 'functions.[functionId].update') - ->label('audits.event', 'function.update') - ->label('audits.resource', 'function/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'update') - ->label('sdk.description', '/docs/references/functions/update-function.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FUNCTION) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') - ->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.', true) - ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), '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 ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) - ->param('events', [], new ArrayList(new FunctionEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true) - ->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true) - ->param('timeout', 15, new Range(1, (int) System::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Maximum execution time in seconds.', true) - ->param('enabled', true, new Boolean(), '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.', true) - ->param('logging', true, new Boolean(), 'Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.', true) - ->param('entrypoint', '', new Text(1028, 0), 'Entrypoint File. This path is relative to the "providerRootDirectory".', true) - ->param('commands', '', new Text(8192, 0), 'Build Commands.', true) - ->param('scopes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of scopes allowed for API Key auto-generated for every execution. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.', true) - ->param('installationId', '', new Text(128, 0), 'Appwrite Installation ID for VCS (Version Controle System) deployment.', true) - ->param('providerRepositoryId', null, new Nullable(new Text(128, 0)), 'Repository ID of the repo linked to the function', true) - ->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the function', true) - ->param('providerSilentMode', false, new Boolean(), '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.', true) - ->param('providerRootDirectory', '', new Text(128, 0), 'Path to function code in the linked repo.', true) - ->param('specification', APP_FUNCTION_SPECIFICATION_DEFAULT, fn (array $plan) => new RuntimeSpecification( - $plan, - Config::getParam('runtime-specifications', []), - App::getEnv('_APP_FUNCTIONS_CPUS', APP_FUNCTION_CPUS_DEFAULT), - App::getEnv('_APP_FUNCTIONS_MEMORY', APP_FUNCTION_MEMORY_DEFAULT) - ), 'Runtime specification for the function and builds.', true, ['plan']) - ->inject('request') - ->inject('response') - ->inject('dbForProject') - ->inject('project') - ->inject('queueForEvents') - ->inject('queueForBuilds') - ->inject('dbForConsole') - ->inject('gitHub') - ->action(function (string $functionId, string $name, string $runtime, array $execute, array $events, string $schedule, int $timeout, bool $enabled, bool $logging, string $entrypoint, string $commands, array $scopes, string $installationId, ?string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github) use ($redeployVcs) { - // TODO: If only branch changes, re-deploy - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $installation = $dbForConsole->getDocument('installations', $installationId); - - if (!empty($installationId) && $installation->isEmpty()) { - throw new Exception(Exception::INSTALLATION_NOT_FOUND); - } - - if (!empty($providerRepositoryId) && (empty($installationId) || empty($providerBranch))) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'When connecting to VCS (Version Control System), you need to provide "installationId" and "providerBranch".'); - } - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - if (empty($runtime)) { - $runtime = $function->getAttribute('runtime'); - } - - $enabled ??= $function->getAttribute('enabled', true); - - $repositoryId = $function->getAttribute('repositoryId', ''); - $repositoryInternalId = $function->getAttribute('repositoryInternalId', ''); - - if (empty($entrypoint)) { - $entrypoint = $function->getAttribute('entrypoint', ''); - } - - $isConnected = !empty($function->getAttribute('providerRepositoryId', '')); - - // Git disconnect logic. Disconnecting only when providerRepositoryId is empty, allowing for continue updates without disconnecting git - if ($isConnected && ($providerRepositoryId !== null && empty($providerRepositoryId))) { - $repositories = $dbForConsole->find('repositories', [ - Query::equal('projectInternalId', [$project->getInternalId()]), - Query::equal('resourceInternalId', [$function->getInternalId()]), - Query::equal('resourceType', ['function']), - Query::limit(100), - ]); - - foreach ($repositories as $repository) { - $dbForConsole->deleteDocument('repositories', $repository->getId()); - } - - $providerRepositoryId = ''; - $installationId = ''; - $providerBranch = ''; - $providerRootDirectory = ''; - $providerSilentMode = true; - $repositoryId = ''; - $repositoryInternalId = ''; - } - - // Git connect logic - if (!$isConnected && !empty($providerRepositoryId)) { - $teamId = $project->getAttribute('teamId', ''); - - $repository = $dbForConsole->createDocument('repositories', new Document([ - '$id' => ID::unique(), - '$permissions' => [ - Permission::read(Role::team(ID::custom($teamId))), - Permission::update(Role::team(ID::custom($teamId), 'owner')), - Permission::update(Role::team(ID::custom($teamId), 'developer')), - Permission::delete(Role::team(ID::custom($teamId), 'owner')), - Permission::delete(Role::team(ID::custom($teamId), 'developer')), - ], - 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), - 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), - 'providerRepositoryId' => $providerRepositoryId, - 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), - 'resourceType' => 'function', - 'providerPullRequestIds' => [] - ])); - - $repositoryId = $repository->getId(); - $repositoryInternalId = $repository->getInternalId(); - } - - $live = true; - - if ( - $function->getAttribute('name') !== $name || - $function->getAttribute('entrypoint') !== $entrypoint || - $function->getAttribute('commands') !== $commands || - $function->getAttribute('providerRootDirectory') !== $providerRootDirectory || - $function->getAttribute('runtime') !== $runtime - ) { - $live = false; - } - - $spec = Config::getParam('runtime-specifications')[$specification] ?? []; - - // Enforce Cold Start if spec limits change. - if ($function->getAttribute('specification') !== $specification && !empty($function->getAttribute('deployment'))) { - $executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST')); - try { - $executor->deleteRuntime($project->getId(), $function->getAttribute('deployment')); - } catch (\Throwable $th) { - // Don't throw if the deployment doesn't exist - if ($th->getCode() !== 404) { - throw $th; - } - } - } - - $function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [ - 'execute' => $execute, - 'name' => $name, - 'runtime' => $runtime, - 'events' => $events, - 'schedule' => $schedule, - 'timeout' => $timeout, - 'enabled' => $enabled, - 'live' => $live, - 'logging' => $logging, - 'entrypoint' => $entrypoint, - 'commands' => $commands, - 'scopes' => $scopes, - 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), - 'providerRepositoryId' => $providerRepositoryId, - 'repositoryId' => $repositoryId, - 'repositoryInternalId' => $repositoryInternalId, - 'providerBranch' => $providerBranch, - 'providerRootDirectory' => $providerRootDirectory, - 'providerSilentMode' => $providerSilentMode, - 'specification' => $specification, - 'search' => implode(' ', [$functionId, $name, $runtime]), - ]))); - - // Redeploy logic - if (!$isConnected && !empty($providerRepositoryId)) { - $redeployVcs($request, $function, $project, $installation, $dbForProject, $queueForBuilds, new Document(), $github); - } - - // Inform scheduler if function is still active - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); - $schedule - ->setAttribute('resourceUpdatedAt', DateTime::now()) - ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); - - $queueForEvents->setParam('functionId', $function->getId()); - - $response->dynamic($function, Response::MODEL_FUNCTION); - }); - -App::get('/v1/functions/:functionId/deployments/:deploymentId/download') - ->groups(['api', 'functions']) - ->desc('Download deployment') - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getDeploymentDownload') - ->label('sdk.description', '/docs/references/functions/get-deployment-download.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', '*/*') - ->label('sdk.methodType', 'location') - ->param('functionId', '', new UID(), 'Function ID.') - ->param('deploymentId', '', new UID(), 'Deployment ID.') - ->inject('response') - ->inject('request') - ->inject('dbForProject') - ->inject('deviceForFunctions') - ->action(function (string $functionId, string $deploymentId, Response $response, Request $request, Database $dbForProject, Device $deviceForFunctions) { - - $function = $dbForProject->getDocument('functions', $functionId); - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $deployment = $dbForProject->getDocument('deployments', $deploymentId); - if ($deployment->isEmpty()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - if ($deployment->getAttribute('resourceId') !== $function->getId()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - $path = $deployment->getAttribute('path', ''); - if (!$deviceForFunctions->exists($path)) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - $response - ->setContentType('application/gzip') - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()) - ->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '.tar.gz"'); - - $size = $deviceForFunctions->getFileSize($path); - $rangeHeader = $request->getHeader('range'); - - if (!empty($rangeHeader)) { - $start = $request->getRangeStart(); - $end = $request->getRangeEnd(); - $unit = $request->getRangeUnit(); - - if ($end === null) { - $end = min(($start + MAX_OUTPUT_CHUNK_SIZE - 1), ($size - 1)); - } - - if ($unit !== 'bytes' || $start >= $end || $end >= $size) { - throw new Exception(Exception::STORAGE_INVALID_RANGE); - } - - $response - ->addHeader('Accept-Ranges', 'bytes') - ->addHeader('Content-Range', 'bytes ' . $start . '-' . $end . '/' . $size) - ->addHeader('Content-Length', $end - $start + 1) - ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); - - $response->send($deviceForFunctions->read($path, $start, ($end - $start + 1))); - } - - if ($size > APP_STORAGE_READ_BUFFER) { - for ($i = 0; $i < ceil($size / MAX_OUTPUT_CHUNK_SIZE); $i++) { - $response->chunk( - $deviceForFunctions->read( - $path, - ($i * MAX_OUTPUT_CHUNK_SIZE), - min(MAX_OUTPUT_CHUNK_SIZE, $size - ($i * MAX_OUTPUT_CHUNK_SIZE)) - ), - (($i + 1) * MAX_OUTPUT_CHUNK_SIZE) >= $size - ); - } - } else { - $response->send($deviceForFunctions->read($path)); - } - }); - -App::patch('/v1/functions/:functionId/deployments/:deploymentId') - ->groups(['api', 'functions']) - ->desc('Update deployment') - ->label('scope', 'functions.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('event', 'functions.[functionId].deployments.[deploymentId].update') - ->label('audits.event', 'deployment.update') - ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'updateDeployment') - ->label('sdk.description', '/docs/references/functions/update-function-deployment.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FUNCTION) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('deploymentId', '', new UID(), 'Deployment ID.') - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->inject('dbForConsole') - ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Event $queueForEvents, Database $dbForConsole) { - - $function = $dbForProject->getDocument('functions', $functionId); - $deployment = $dbForProject->getDocument('deployments', $deploymentId); - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - if ($deployment->isEmpty()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - if ($build->isEmpty()) { - throw new Exception(Exception::BUILD_NOT_FOUND); - } - - if ($build->getAttribute('status') !== 'ready') { - throw new Exception(Exception::BUILD_NOT_READY); - } - - $function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [ - 'deploymentInternalId' => $deployment->getInternalId(), - 'deployment' => $deployment->getId(), - ]))); - - // Inform scheduler if function is still active - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); - $schedule - ->setAttribute('resourceUpdatedAt', DateTime::now()) - ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); - - $queueForEvents - ->setParam('functionId', $function->getId()) - ->setParam('deploymentId', $deployment->getId()); - - $response->dynamic($function, Response::MODEL_FUNCTION); - }); - -App::delete('/v1/functions/:functionId') - ->groups(['api', 'functions']) - ->desc('Delete function') - ->label('scope', 'functions.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('event', 'functions.[functionId].delete') - ->label('audits.event', 'function.delete') - ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/functions/delete-function.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) - ->param('functionId', '', new UID(), 'Function ID.') - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDeletes') - ->inject('queueForEvents') - ->inject('dbForConsole') - ->action(function (string $functionId, Response $response, Database $dbForProject, Delete $queueForDeletes, Event $queueForEvents, Database $dbForConsole) { - - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - if (!$dbForProject->deleteDocument('functions', $function->getId())) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove function from DB'); - } - - // Inform scheduler to no longer run function - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); - $schedule - ->setAttribute('resourceUpdatedAt', DateTime::now()) - ->setAttribute('active', false); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); - - $queueForDeletes - ->setType(DELETE_TYPE_DOCUMENT) - ->setDocument($function); - - $queueForEvents->setParam('functionId', $function->getId()); - - $response->noContent(); - }); - -App::post('/v1/functions/:functionId/deployments') - ->groups(['api', 'functions']) - ->desc('Create deployment') - ->label('scope', 'functions.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('event', 'functions.[functionId].deployments.[deploymentId].create') - ->label('audits.event', 'deployment.create') - ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'createDeployment') - ->label('sdk.methodType', 'upload') - ->label('sdk.description', '/docs/references/functions/create-deployment.md') - ->label('sdk.packaging', true) - ->label('sdk.request.type', 'multipart/form-data') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DEPLOYMENT) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('entrypoint', null, new Text(1028), 'Entrypoint File.', true) - ->param('commands', null, new Text(8192, 0), 'Build Commands.', true) - ->param('code', [], new File(), '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.', skipValidation: true) - ->param('activate', false, new Boolean(true), 'Automatically activate the deployment when it is finished building.') - ->inject('request') - ->inject('response') - ->inject('dbForProject') - ->inject('queueForEvents') - ->inject('project') - ->inject('deviceForFunctions') - ->inject('deviceForLocal') - ->inject('queueForBuilds') - ->action(function (string $functionId, ?string $entrypoint, ?string $commands, mixed $code, mixed $activate, Request $request, Response $response, Database $dbForProject, Event $queueForEvents, Document $project, Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds) { - - $activate = \strval($activate) === 'true' || \strval($activate) === '1'; - - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - if ($entrypoint === null) { - $entrypoint = $function->getAttribute('entrypoint', ''); - } - - if ($commands === null) { - $commands = $function->getAttribute('commands', ''); - } - - if (empty($entrypoint)) { - throw new Exception(Exception::FUNCTION_ENTRYPOINT_MISSING); - } - - $file = $request->getFiles('code'); - - // GraphQL multipart spec adds files with index keys - if (empty($file)) { - $file = $request->getFiles(0); - } - - if (empty($file)) { - throw new Exception(Exception::STORAGE_FILE_EMPTY, 'No file sent'); - } - - $fileExt = new FileExt([FileExt::TYPE_GZIP]); - $fileSizeValidator = new FileSize(System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT', '30000000')); - $upload = new Upload(); - - // Make sure we handle a single file and multiple files the same way - $fileName = (\is_array($file['name']) && isset($file['name'][0])) ? $file['name'][0] : $file['name']; - $fileTmpName = (\is_array($file['tmp_name']) && isset($file['tmp_name'][0])) ? $file['tmp_name'][0] : $file['tmp_name']; - $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; - - if (!$fileExt->isValid($file['name'])) { // Check if file type is allowed - throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED); - } - - $contentRange = $request->getHeader('content-range'); - $deploymentId = ID::unique(); - $chunk = 1; - $chunks = 1; - - if (!empty($contentRange)) { - $start = $request->getContentRangeStart(); - $end = $request->getContentRangeEnd(); - $fileSize = $request->getContentRangeSize(); - $deploymentId = $request->getHeader('x-appwrite-id', $deploymentId); - // TODO make `end >= $fileSize` in next breaking version - if (is_null($start) || is_null($end) || is_null($fileSize) || $end > $fileSize) { - throw new Exception(Exception::STORAGE_INVALID_CONTENT_RANGE); - } - - // TODO remove the condition that checks `$end === $fileSize` in next breaking version - if ($end === $fileSize - 1 || $end === $fileSize) { - //if it's a last chunks the chunk size might differ, so we set the $chunks and $chunk to notify it's last chunk - $chunks = $chunk = -1; - } else { - // Calculate total number of chunks based on the chunk size i.e ($rangeEnd - $rangeStart) - $chunks = (int) ceil($fileSize / ($end + 1 - $start)); - $chunk = (int) ($start / ($end + 1 - $start)) + 1; - } - } - - if (!$fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit - throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE); - } - - if (!$upload->isValid($fileTmpName)) { - throw new Exception(Exception::STORAGE_INVALID_FILE); - } - - // Save to storage - $fileSize ??= $deviceForLocal->getFileSize($fileTmpName); - $path = $deviceForFunctions->getPath($deploymentId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); - $deployment = $dbForProject->getDocument('deployments', $deploymentId); - - $metadata = ['content_type' => $deviceForLocal->getFileMimeType($fileTmpName)]; - if (!$deployment->isEmpty()) { - $chunks = $deployment->getAttribute('chunksTotal', 1); - $metadata = $deployment->getAttribute('metadata', []); - if ($chunk === -1) { - $chunk = $chunks; - } - } - - $chunksUploaded = $deviceForFunctions->upload($fileTmpName, $path, $chunk, $chunks, $metadata); - - if (empty($chunksUploaded)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed moving file'); - } - - $type = $request->getHeader('x-sdk-language') === 'cli' ? 'cli' : 'manual'; - - if ($chunksUploaded === $chunks) { - if ($activate) { - // Remove deploy for all other deployments. - $activeDeployments = $dbForProject->find('deployments', [ - Query::equal('activate', [true]), - Query::equal('resourceId', [$functionId]), - Query::equal('resourceType', ['functions']) - ]); - - foreach ($activeDeployments as $activeDeployment) { - $activeDeployment->setAttribute('activate', false); - $dbForProject->updateDocument('deployments', $activeDeployment->getId(), $activeDeployment); - } - } - - $fileSize = $deviceForFunctions->getFileSize($path); - - if ($deployment->isEmpty()) { - $deployment = $dbForProject->createDocument('deployments', new Document([ - '$id' => $deploymentId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], - 'resourceInternalId' => $function->getInternalId(), - 'resourceId' => $function->getId(), - 'resourceType' => 'functions', - 'buildInternalId' => '', - 'entrypoint' => $entrypoint, - 'commands' => $commands, - 'path' => $path, - 'size' => $fileSize, - 'search' => implode(' ', [$deploymentId, $entrypoint]), - 'activate' => $activate, - 'metadata' => $metadata, - 'type' => $type - ])); - } else { - $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('size', $fileSize)->setAttribute('metadata', $metadata)); - } - - // Start the build - $queueForBuilds - ->setType(BUILD_TYPE_DEPLOYMENT) - ->setResource($function) - ->setDeployment($deployment); - } else { - if ($deployment->isEmpty()) { - $deployment = $dbForProject->createDocument('deployments', new Document([ - '$id' => $deploymentId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], - 'resourceInternalId' => $function->getInternalId(), - 'resourceId' => $function->getId(), - 'resourceType' => 'functions', - 'buildInternalId' => '', - 'entrypoint' => $entrypoint, - 'commands' => $commands, - 'path' => $path, - 'size' => $fileSize, - 'chunksTotal' => $chunks, - 'chunksUploaded' => $chunksUploaded, - 'search' => implode(' ', [$deploymentId, $entrypoint]), - 'activate' => $activate, - 'metadata' => $metadata, - 'type' => $type - ])); - } else { - $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('chunksUploaded', $chunksUploaded)->setAttribute('metadata', $metadata)); - } - } - - $metadata = null; - - $queueForEvents - ->setParam('functionId', $function->getId()) - ->setParam('deploymentId', $deployment->getId()); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($deployment, Response::MODEL_DEPLOYMENT); - }); - -App::get('/v1/functions/:functionId/deployments') - ->groups(['api', 'functions']) - ->desc('List deployments') - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listDeployments') - ->label('sdk.description', '/docs/references/functions/list-deployments.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DEPLOYMENT_LIST) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('queries', [], new Deployments(), '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(', ', Deployments::ALLOWED_ATTRIBUTES), true) - ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $functionId, array $queries, string $search, Response $response, Database $dbForProject) { - - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - if (!empty($search)) { - $queries[] = Query::search('search', $search); - } - - // Set resource queries - $queries[] = Query::equal('resourceInternalId', [$function->getInternalId()]); - $queries[] = Query::equal('resourceType', ['functions']); - - /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ - $cursor = \array_filter($queries, function ($query) { - return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - }); - $cursor = reset($cursor); - if ($cursor) { - /** @var Query $cursor */ - - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $deploymentId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('deployments', $deploymentId); - - if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Deployment '{$deploymentId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorDocument); - } - - $filterQueries = Query::groupByType($queries)['filters']; - - $results = $dbForProject->find('deployments', $queries); - $total = $dbForProject->count('deployments', $filterQueries, APP_LIMIT_COUNT); - - foreach ($results as $result) { - $build = $dbForProject->getDocument('builds', $result->getAttribute('buildId', '')); - $result->setAttribute('status', $build->getAttribute('status', 'processing')); - $result->setAttribute('buildLogs', $build->getAttribute('logs', '')); - $result->setAttribute('buildTime', $build->getAttribute('duration', 0)); - $result->setAttribute('buildSize', $build->getAttribute('size', 0)); - $result->setAttribute('size', $result->getAttribute('size', 0)); - } - - $response->dynamic(new Document([ - 'deployments' => $results, - 'total' => $total, - ]), Response::MODEL_DEPLOYMENT_LIST); - }); - -App::get('/v1/functions/:functionId/deployments/:deploymentId') - ->groups(['api', 'functions']) - ->desc('Get deployment') - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getDeployment') - ->label('sdk.description', '/docs/references/functions/get-deployment.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DEPLOYMENT) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('deploymentId', '', new UID(), 'Deployment ID.') - ->inject('response') - ->inject('dbForProject') - ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject) { - - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $deployment = $dbForProject->getDocument('deployments', $deploymentId); - - if ($deployment->getAttribute('resourceId') !== $function->getId()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - if ($deployment->isEmpty()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); - $deployment->setAttribute('status', $build->getAttribute('status', 'waiting')); - $deployment->setAttribute('buildLogs', $build->getAttribute('logs', '')); - $deployment->setAttribute('buildTime', $build->getAttribute('duration', 0)); - $deployment->setAttribute('buildSize', $build->getAttribute('size', 0)); - $deployment->setAttribute('size', $deployment->getAttribute('size', 0)); - - $response->dynamic($deployment, Response::MODEL_DEPLOYMENT); - }); - -App::delete('/v1/functions/:functionId/deployments/:deploymentId') - ->groups(['api', 'functions']) - ->desc('Delete deployment') - ->label('scope', 'functions.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('event', 'functions.[functionId].deployments.[deploymentId].delete') - ->label('audits.event', 'deployment.delete') - ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'deleteDeployment') - ->label('sdk.description', '/docs/references/functions/delete-deployment.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('deploymentId', '', new UID(), 'Deployment ID.') - ->inject('response') - ->inject('dbForProject') - ->inject('queueForDeletes') - ->inject('queueForEvents') - ->inject('deviceForFunctions') - ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Delete $queueForDeletes, Event $queueForEvents, Device $deviceForFunctions) { - - $function = $dbForProject->getDocument('functions', $functionId); - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $deployment = $dbForProject->getDocument('deployments', $deploymentId); - if ($deployment->isEmpty()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - if ($deployment->getAttribute('resourceId') !== $function->getId()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - if (!$dbForProject->deleteDocument('deployments', $deployment->getId())) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from DB'); - } - - if (!empty($deployment->getAttribute('path', ''))) { - if (!($deviceForFunctions->delete($deployment->getAttribute('path', '')))) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from storage'); - } - } - - if ($function->getAttribute('deployment') === $deployment->getId()) { // Reset function deployment - $function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [ - 'deployment' => '', - 'deploymentInternalId' => '', - ]))); - } - - $queueForEvents - ->setParam('functionId', $function->getId()) - ->setParam('deploymentId', $deployment->getId()); - - $queueForDeletes - ->setType(DELETE_TYPE_DOCUMENT) - ->setDocument($deployment); - - $response->noContent(); - }); - -App::post('/v1/functions/:functionId/deployments/:deploymentId/build') - ->alias('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId') - ->groups(['api', 'functions']) - ->desc('Rebuild deployment') - ->label('scope', 'functions.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('event', 'functions.[functionId].deployments.[deploymentId].update') - ->label('audits.event', 'deployment.update') - ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'createBuild') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('deploymentId', '', new UID(), 'Deployment ID.') - ->param('buildId', '', new UID(), 'Build unique ID.', true) // added as optional param for backward compatibility - ->inject('request') - ->inject('response') - ->inject('dbForProject') - ->inject('project') - ->inject('queueForEvents') - ->inject('queueForBuilds') - ->inject('deviceForFunctions') - ->action(function (string $functionId, string $deploymentId, string $buildId, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Device $deviceForFunctions) { - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - $deployment = $dbForProject->getDocument('deployments', $deploymentId); - - if ($deployment->isEmpty()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - $path = $deployment->getAttribute('path'); - if (empty($path) || !$deviceForFunctions->exists($path)) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - $deploymentId = ID::unique(); - - $destination = $deviceForFunctions->getPath($deploymentId . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); - $deviceForFunctions->transfer($path, $destination, $deviceForFunctions); - - $deployment->removeAttribute('$internalId'); - $deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([ - '$internalId' => '', - '$id' => $deploymentId, - 'buildId' => '', - 'buildInternalId' => '', - 'path' => $destination, - 'entrypoint' => $function->getAttribute('entrypoint'), - 'commands' => $function->getAttribute('commands', ''), - 'search' => implode(' ', [$deploymentId, $function->getAttribute('entrypoint')]), - ])); - - $queueForBuilds - ->setType(BUILD_TYPE_DEPLOYMENT) - ->setResource($function) - ->setDeployment($deployment); - - $queueForEvents - ->setParam('functionId', $function->getId()) - ->setParam('deploymentId', $deployment->getId()); - - $response->noContent(); - }); - -App::patch('/v1/functions/:functionId/deployments/:deploymentId/build') - ->groups(['api', 'functions']) - ->desc('Cancel deployment') - ->label('scope', 'functions.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('audits.event', 'deployment.update') - ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'updateDeploymentBuild') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUILD) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('deploymentId', '', new UID(), 'Deployment ID.') - ->inject('response') - ->inject('dbForProject') - ->inject('project') - ->inject('queueForEvents') - ->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, Document $project, Event $queueForEvents) { - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $deployment = $dbForProject->getDocument('deployments', $deploymentId); - - if ($deployment->isEmpty()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); - } - - $build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); - - if ($build->isEmpty()) { - $buildId = ID::unique(); - $build = $dbForProject->createDocument('builds', new Document([ - '$id' => $buildId, - '$permissions' => [], - 'startTime' => DateTime::now(), - 'deploymentInternalId' => $deployment->getInternalId(), - 'deploymentId' => $deployment->getId(), - 'status' => 'canceled', - 'path' => '', - 'runtime' => $function->getAttribute('runtime'), - 'source' => $deployment->getAttribute('path', ''), - 'sourceType' => '', - 'logs' => '', - 'duration' => 0, - 'size' => 0 - ])); - - $deployment->setAttribute('buildId', $build->getId()); - $deployment->setAttribute('buildInternalId', $build->getInternalId()); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - } else { - if (\in_array($build->getAttribute('status'), ['ready', 'failed'])) { - throw new Exception(Exception::BUILD_ALREADY_COMPLETED); - } - - $startTime = new \DateTime($build->getAttribute('startTime')); - $endTime = new \DateTime('now'); - $duration = $endTime->getTimestamp() - $startTime->getTimestamp(); - - $build = $dbForProject->updateDocument('builds', $build->getId(), $build->setAttributes([ - 'endTime' => DateTime::now(), - 'duration' => $duration, - 'status' => 'canceled' - ])); - } - - $dbForProject->purgeCachedDocument('deployments', $deployment->getId()); - - try { - $executor = new Executor(App::getEnv('_APP_EXECUTOR_HOST')); - $executor->deleteRuntime($project->getId(), $deploymentId . "-build"); - } catch (\Throwable $th) { - // Don't throw if the deployment doesn't exist - if ($th->getCode() !== 404) { - throw $th; - } - } - - $queueForEvents - ->setParam('functionId', $function->getId()) - ->setParam('deploymentId', $deployment->getId()); - - $response->dynamic($build, Response::MODEL_BUILD); - }); - -App::post('/v1/functions/:functionId/executions') - ->groups(['api', 'functions']) - ->desc('Create execution') - ->label('scope', 'execution.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('event', 'functions.[functionId].executions.[executionId].create') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'createExecution') - ->label('sdk.description', '/docs/references/functions/create-execution.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_MULTIPART) - ->label('sdk.response.model', Response::MODEL_EXECUTION) - ->label('sdk.request.type', Response::CONTENT_TYPE_JSON) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('body', '', new Text(10485760, 0), 'HTTP body of execution. Default value is empty string.', true) - ->param('async', false, new Boolean(true), 'Execute code in the background. Default value is false.', true) - ->param('path', '/', new Text(2048), 'HTTP path of execution. Path can include query params. Default value is /', true) - ->param('method', 'POST', new Whitelist(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], true), 'HTTP method of execution. Default value is GET.', true) - ->param('headers', [], new AnyOf([new Assoc(), new Text(65535)], AnyOf::TYPE_MIXED), 'HTTP headers of execution. Defaults to empty.', true) - ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true, precision: DateTimeValidator::PRECISION_MINUTES, offset: 60), '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.', true) - ->inject('response') - ->inject('request') - ->inject('project') - ->inject('dbForProject') - ->inject('dbForConsole') - ->inject('user') - ->inject('queueForEvents') - ->inject('queueForUsage') - ->inject('queueForFunctions') - ->inject('geodb') - ->action(function (string $functionId, string $body, mixed $async, string $path, string $method, mixed $headers, ?string $scheduledAt, Response $response, Request $request, Document $project, Database $dbForProject, Database $dbForConsole, Document $user, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb) { - $async = \strval($async) === 'true' || \strval($async) === '1'; - - if (!$async && !is_null($scheduledAt)) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Scheduled executions must run asynchronously. Set scheduledAt to a future date, or set async to true.'); - } - - /** - * @var array<string, mixed> $headers - */ - $assocParams = ['headers']; - foreach ($assocParams as $assocParam) { - if (!empty('headers') && !is_array($$assocParam)) { - $$assocParam = \json_decode($$assocParam, true); - } - } - - $booleanParams = ['async']; - foreach ($booleanParams as $booleamParam) { - if (!empty($$booleamParam) && !is_bool($$booleamParam)) { - $$booleamParam = $$booleamParam === "true" ? true : false; - } - } - - // 'headers' validator - $validator = new Headers(); - if (!$validator->isValid($headers)) { - throw new Exception($validator->getDescription(), 400); - } - - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $version = $function->getAttribute('version', 'v2'); - $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); - $spec = Config::getParam('runtime-specifications')[$function->getAttribute('specification', APP_FUNCTION_SPECIFICATION_DEFAULT)]; - - $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null; - - if (\is_null($runtime)) { - throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); - } - - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', ''))); - - if ($deployment->getAttribute('resourceId') !== $function->getId()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); - } - - if ($deployment->isEmpty()) { - throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); - } - - /** Check if build has completed */ - $build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); - if ($build->isEmpty()) { - throw new Exception(Exception::BUILD_NOT_FOUND); - } - - if ($build->getAttribute('status') !== 'ready') { - throw new Exception(Exception::BUILD_NOT_READY); - } - - $validator = new Authorization('execute'); - - if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function - throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); - } - - $jwt = ''; // initialize - if (!$user->isEmpty()) { // If userId exists, generate a JWT for function - $sessions = $user->getAttribute('sessions', []); - $current = new Document(); - - foreach ($sessions as $session) { - /** @var Utopia\Database\Document $session */ - if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too - $current = $session; - } - } - - if (!$current->isEmpty()) { - $jwtExpiry = $function->getAttribute('timeout', 900); - $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $jwtExpiry, 0); - $jwt = $jwtObj->encode([ - 'userId' => $user->getId(), - 'sessionId' => $current->getId(), - ]); - } - } - - $jwtExpiry = $function->getAttribute('timeout', 900); - $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $jwtExpiry, 0); - $apiKey = $jwtObj->encode([ - 'projectId' => $project->getId(), - 'scopes' => $function->getAttribute('scopes', []) - ]); - - $headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $apiKey; - $headers['x-appwrite-trigger'] = 'http'; - $headers['x-appwrite-user-id'] = $user->getId() ?? ''; - $headers['x-appwrite-user-jwt'] = $jwt ?? ''; - $headers['x-appwrite-country-code'] = ''; - $headers['x-appwrite-continent-code'] = ''; - $headers['x-appwrite-continent-eu'] = 'false'; - - $ip = $headers['x-real-ip'] ?? ''; - if (!empty($ip)) { - $record = $geodb->get($ip); - - if ($record) { - $eu = Config::getParam('locale-eu'); - - $headers['x-appwrite-country-code'] = $record['country']['iso_code'] ?? ''; - $headers['x-appwrite-continent-code'] = $record['continent']['code'] ?? ''; - $headers['x-appwrite-continent-eu'] = (\in_array($record['country']['iso_code'], $eu)) ? 'true' : 'false'; - } - } - - $headersFiltered = []; - foreach ($headers as $key => $value) { - if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_REQUEST)) { - $headersFiltered[] = ['name' => $key, 'value' => $value]; - } - } - - $executionId = ID::unique(); - - $status = $async ? 'waiting' : 'processing'; - - if (!is_null($scheduledAt)) { - $status = 'scheduled'; - } - - $execution = new Document([ - '$id' => $executionId, - '$permissions' => !$user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], - 'functionInternalId' => $function->getInternalId(), - 'functionId' => $function->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), - 'deploymentId' => $deployment->getId(), - 'trigger' => (!is_null($scheduledAt)) ? 'schedule' : 'http', - 'status' => $status, // waiting / processing / completed / failed / scheduled - 'responseStatusCode' => 0, - 'responseHeaders' => [], - 'requestPath' => $path, - 'requestMethod' => $method, - 'requestHeaders' => $headersFiltered, - 'errors' => '', - 'logs' => '', - 'duration' => 0.0, - 'search' => implode(' ', [$functionId, $executionId]), - ]); - - $queueForEvents - ->setParam('functionId', $function->getId()) - ->setParam('executionId', $execution->getId()) - ->setContext('function', $function); - - if ($async) { - if (is_null($scheduledAt)) { - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); - $queueForFunctions - ->setType('http') - ->setExecution($execution) - ->setFunction($function) - ->setBody($body) - ->setHeaders($headers) - ->setPath($path) - ->setMethod($method) - ->setJWT($jwt) - ->setProject($project) - ->setUser($user) - ->setParam('functionId', $function->getId()) - ->setParam('executionId', $execution->getId()) - ->trigger(); - } else { - $data = [ - 'headers' => $headers, - 'path' => $path, - 'method' => $method, - 'body' => $body, - 'userId' => $user->getId() - ]; - - $schedule = $dbForConsole->createDocument('schedules', new Document([ - 'region' => System::getEnv('_APP_REGION', 'default'), - 'resourceType' => ScheduleExecutions::getSupportedResource(), - 'resourceId' => $execution->getId(), - 'resourceInternalId' => $execution->getInternalId(), - 'resourceUpdatedAt' => DateTime::now(), - 'projectId' => $project->getId(), - 'schedule' => $scheduledAt, - 'data' => $data, - 'active' => true, - ])); - - $execution = $execution - ->setAttribute('scheduleId', $schedule->getId()) - ->setAttribute('scheduleInternalId', $schedule->getInternalId()) - ->setAttribute('scheduledAt', $scheduledAt); - - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); - } - - return $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($execution, Response::MODEL_EXECUTION); - } - - $durationStart = \microtime(true); - - $vars = []; - - // V2 vars - if ($version === 'v2') { - $vars = \array_merge($vars, [ - 'APPWRITE_FUNCTION_TRIGGER' => $headers['x-appwrite-trigger'] ?? '', - 'APPWRITE_FUNCTION_DATA' => $body ?? '', - 'APPWRITE_FUNCTION_USER_ID' => $headers['x-appwrite-user-id'] ?? '', - 'APPWRITE_FUNCTION_JWT' => $headers['x-appwrite-user-jwt'] ?? '' - ]); - } - - // Shared vars - foreach ($function->getAttribute('varsProject', []) as $var) { - $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); - } - - // Function vars - foreach ($function->getAttribute('vars', []) as $var) { - $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); - } - - $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_DOMAIN'); - $endpoint = $protocol . '://' . $hostname . "/v1"; - - // Appwrite vars - $vars = \array_merge($vars, [ - 'APPWRITE_FUNCTION_API_ENDPOINT' => $endpoint, - 'APPWRITE_FUNCTION_ID' => $functionId, - 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name'), - 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), - 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), - 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', - 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', - 'APPWRITE_FUNCTION_CPUS' => $spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT, - 'APPWRITE_FUNCTION_MEMORY' => $spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT, - 'APPWRITE_VERSION' => APP_VERSION_STABLE, - 'APPWRITE_REGION' => $project->getAttribute('region'), - 'APPWRITE_DEPLOYMENT_TYPE' => $deployment->getAttribute('type', ''), - 'APPWRITE_VCS_REPOSITORY_ID' => $deployment->getAttribute('providerRepositoryId', ''), - 'APPWRITE_VCS_REPOSITORY_NAME' => $deployment->getAttribute('providerRepositoryName', ''), - 'APPWRITE_VCS_REPOSITORY_OWNER' => $deployment->getAttribute('providerRepositoryOwner', ''), - 'APPWRITE_VCS_REPOSITORY_URL' => $deployment->getAttribute('providerRepositoryUrl', ''), - 'APPWRITE_VCS_REPOSITORY_BRANCH' => $deployment->getAttribute('providerBranch', ''), - 'APPWRITE_VCS_REPOSITORY_BRANCH_URL' => $deployment->getAttribute('providerBranchUrl', ''), - 'APPWRITE_VCS_COMMIT_HASH' => $deployment->getAttribute('providerCommitHash', ''), - 'APPWRITE_VCS_COMMIT_MESSAGE' => $deployment->getAttribute('providerCommitMessage', ''), - 'APPWRITE_VCS_COMMIT_URL' => $deployment->getAttribute('providerCommitUrl', ''), - 'APPWRITE_VCS_COMMIT_AUTHOR_NAME' => $deployment->getAttribute('providerCommitAuthor', ''), - 'APPWRITE_VCS_COMMIT_AUTHOR_URL' => $deployment->getAttribute('providerCommitAuthorUrl', ''), - 'APPWRITE_VCS_ROOT_DIRECTORY' => $deployment->getAttribute('providerRootDirectory', ''), - ]); - - /** Execute function */ - $executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST')); - try { - $version = $function->getAttribute('version', 'v2'); - $command = $runtime['startCommand']; - $command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"'; - $executionResponse = $executor->createExecution( - projectId: $project->getId(), - deploymentId: $deployment->getId(), - body: \strlen($body) > 0 ? $body : null, - variables: $vars, - timeout: $function->getAttribute('timeout', 0), - image: $runtime['image'], - source: $build->getAttribute('path', ''), - entrypoint: $deployment->getAttribute('entrypoint', ''), - version: $version, - path: $path, - method: $method, - headers: $headers, - runtimeEntrypoint: $command, - cpus: $spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT, - memory: $spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT, - logging: $function->getAttribute('logging', true), - requestTimeout: 30 - ); - - $headersFiltered = []; - foreach ($executionResponse['headers'] as $key => $value) { - if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) { - $headersFiltered[] = ['name' => $key, 'value' => $value]; - } - } - - /** Update execution status */ - $status = $executionResponse['statusCode'] >= 500 ? 'failed' : 'completed'; - $execution->setAttribute('status', $status); - $execution->setAttribute('responseStatusCode', $executionResponse['statusCode']); - $execution->setAttribute('responseHeaders', $headersFiltered); - $execution->setAttribute('logs', $executionResponse['logs']); - $execution->setAttribute('errors', $executionResponse['errors']); - $execution->setAttribute('duration', $executionResponse['duration']); - } catch (\Throwable $th) { - $durationEnd = \microtime(true); - - $execution - ->setAttribute('duration', $durationEnd - $durationStart) - ->setAttribute('status', 'failed') - ->setAttribute('responseStatusCode', 500) - ->setAttribute('errors', $th->getMessage() . '\nError Code: ' . $th->getCode()); - Console::error($th->getMessage()); - - if ($th instanceof AppwriteException) { - throw $th; - } - } finally { - $queueForUsage - ->addMetric(METRIC_EXECUTIONS, 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), 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(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))) - ; - - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); - } - - $roles = Authorization::getRoles(); - $isPrivilegedUser = Auth::isPrivilegedUser($roles); - $isAppUser = Auth::isAppUser($roles); - - if (!$isPrivilegedUser && !$isAppUser) { - $execution->setAttribute('logs', ''); - $execution->setAttribute('errors', ''); - } - - $headers = []; - foreach (($executionResponse['headers'] ?? []) as $key => $value) { - $headers[] = ['name' => $key, 'value' => $value]; - } - - $execution->setAttribute('responseBody', $executionResponse['body'] ?? ''); - $execution->setAttribute('responseHeaders', $headers); - - $acceptTypes = \explode(', ', $request->getHeader('accept')); - foreach ($acceptTypes as $acceptType) { - if (\str_starts_with($acceptType, 'application/json') || \str_starts_with($acceptType, 'application/*')) { - $response->setContentType(Response::CONTENT_TYPE_JSON); - break; - } elseif (\str_starts_with($acceptType, 'multipart/form-data') || \str_starts_with($acceptType, 'multipart/*')) { - $response->setContentType(Response::CONTENT_TYPE_MULTIPART); - break; - } - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($execution, Response::MODEL_EXECUTION); - }); - -App::get('/v1/functions/:functionId/executions') - ->groups(['api', 'functions']) - ->desc('List executions') - ->label('scope', 'execution.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listExecutions') - ->label('sdk.description', '/docs/references/functions/list-executions.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_EXECUTION_LIST) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('queries', [], new Executions(), '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(', ', Executions::ALLOWED_ATTRIBUTES), true) - ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('mode') - ->action(function (string $functionId, array $queries, string $search, Response $response, Database $dbForProject, string $mode) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - - if (!empty($search)) { - $queries[] = Query::search('search', $search); - } - - // Set internal queries - $queries[] = Query::equal('functionId', [$function->getId()]); - - /** - * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries - */ - $cursor = \array_filter($queries, function ($query) { - return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - }); - $cursor = reset($cursor); - if ($cursor) { - /** @var Query $cursor */ - - $validator = new Cursor(); - if (!$validator->isValid($cursor)) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); - } - - $executionId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('executions', $executionId); - - if ($cursorDocument->isEmpty()) { - throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Execution '{$executionId}' for the 'cursor' value not found."); - } - - $cursor->setValue($cursorDocument); - } - - $filterQueries = Query::groupByType($queries)['filters']; - - $results = $dbForProject->find('executions', $queries); - $total = $dbForProject->count('executions', $filterQueries, APP_LIMIT_COUNT); - - $roles = Authorization::getRoles(); - $isPrivilegedUser = Auth::isPrivilegedUser($roles); - $isAppUser = Auth::isAppUser($roles); - if (!$isPrivilegedUser && !$isAppUser) { - $results = array_map(function ($execution) { - $execution->setAttribute('logs', ''); - $execution->setAttribute('errors', ''); - return $execution; - }, $results); - } - - $response->dynamic(new Document([ - 'executions' => $results, - 'total' => $total, - ]), Response::MODEL_EXECUTION_LIST); - }); - -App::get('/v1/functions/:functionId/executions/:executionId') - ->groups(['api', 'functions']) - ->desc('Get execution') - ->label('scope', 'execution.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getExecution') - ->label('sdk.description', '/docs/references/functions/get-execution.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_EXECUTION) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('executionId', '', new UID(), 'Execution ID.') - ->inject('response') - ->inject('dbForProject') - ->inject('mode') - ->action(function (string $functionId, string $executionId, Response $response, Database $dbForProject, string $mode) { - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $execution = $dbForProject->getDocument('executions', $executionId); - - if ($execution->getAttribute('functionId') !== $function->getId()) { - throw new Exception(Exception::EXECUTION_NOT_FOUND); - } - - if ($execution->isEmpty()) { - throw new Exception(Exception::EXECUTION_NOT_FOUND); - } - - $roles = Authorization::getRoles(); - $isPrivilegedUser = Auth::isPrivilegedUser($roles); - $isAppUser = Auth::isAppUser($roles); - if (!$isPrivilegedUser && !$isAppUser) { - $execution->setAttribute('logs', ''); - $execution->setAttribute('errors', ''); - } - - $response->dynamic($execution, Response::MODEL_EXECUTION); - }); - -App::delete('/v1/functions/:functionId/executions/:executionId') - ->groups(['api', 'functions']) - ->desc('Delete execution') - ->label('scope', 'execution.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('event', 'functions.[functionId].executions.[executionId].delete') - ->label('audits.event', 'executions.delete') - ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'deleteExecution') - ->label('sdk.description', '/docs/references/functions/delete-execution.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('executionId', '', new UID(), 'Execution ID.') - ->inject('response') - ->inject('dbForProject') - ->inject('dbForConsole') - ->inject('queueForEvents') - ->action(function (string $functionId, string $executionId, Response $response, Database $dbForProject, Database $dbForConsole, Event $queueForEvents) { - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $execution = $dbForProject->getDocument('executions', $executionId); - if ($execution->isEmpty()) { - throw new Exception(Exception::EXECUTION_NOT_FOUND); - } - - if ($execution->getAttribute('functionId') !== $function->getId()) { - throw new Exception(Exception::EXECUTION_NOT_FOUND); - } - $status = $execution->getAttribute('status'); - - if (!in_array($status, ['completed', 'failed', 'scheduled'])) { - throw new Exception(Exception::EXECUTION_IN_PROGRESS); - } - - if (!$dbForProject->deleteDocument('executions', $execution->getId())) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove execution from DB'); - } - - if ($status === 'scheduled') { - $schedule = $dbForConsole->findOne('schedules', [ - Query::equal('resourceId', [$execution->getId()]), - Query::equal('resourceType', [ScheduleExecutions::getSupportedResource()]), - Query::equal('active', [true]), - ]); - - if (!$schedule->isEmpty()) { - $schedule - ->setAttribute('resourceUpdatedAt', DateTime::now()) - ->setAttribute('active', false); - - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); - } - } - - $queueForEvents - ->setParam('functionId', $function->getId()) - ->setParam('executionId', $execution->getId()) - ->setPayload($response->output($execution, Response::MODEL_EXECUTION)); - - $response->noContent(); - }); - -// Variables - -App::post('/v1/functions/:functionId/variables') - ->desc('Create variable') - ->groups(['api', 'functions']) - ->label('scope', 'functions.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('audits.event', 'variable.create') - ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'createVariable') - ->label('sdk.description', '/docs/references/functions/create-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) - ->param('functionId', '', new UID(), 'Function unique ID.', false) - ->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false) - ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false) - ->param('secret', false, new Boolean(), 'Is secret? Secret variables can only be updated or deleted, they cannot be read.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (string $functionId, string $key, string $value, bool $secret, Response $response, Database $dbForProject, Database $dbForConsole) { - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $variableId = ID::unique(); - - $variable = new Document([ - '$id' => $variableId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], - 'resourceInternalId' => $function->getInternalId(), - 'resourceId' => $function->getId(), - 'resourceType' => 'function', - 'key' => $key, - 'value' => $value, - 'secret' => $secret, - 'search' => implode(' ', [$variableId, $function->getId(), $key, 'function']), - ]); - - try { - $variable = $dbForProject->createDocument('variables', $variable); - } catch (DuplicateException $th) { - throw new Exception(Exception::VARIABLE_ALREADY_EXISTS); - } - - $dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false)); - - // Inform scheduler to pull the latest changes - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); - $schedule - ->setAttribute('resourceUpdatedAt', DateTime::now()) - ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($variable, Response::MODEL_VARIABLE); - }); - -App::get('/v1/functions/:functionId/variables') - ->desc('List variables') - ->groups(['api', 'functions']) - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listVariables') - ->label('sdk.description', '/docs/references/functions/list-variables.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE_LIST) - ->param('functionId', '', new UID(), 'Function unique ID.', false) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $functionId, Response $response, Database $dbForProject) { - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $response->dynamic(new Document([ - 'variables' => $function->getAttribute('vars', []), - 'total' => \count($function->getAttribute('vars', [])), - ]), Response::MODEL_VARIABLE_LIST); - }); - -App::get('/v1/functions/:functionId/variables/:variableId') - ->desc('Get variable') - ->groups(['api', 'functions']) - ->label('scope', 'functions.read') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getVariable') - ->label('sdk.description', '/docs/references/functions/get-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) - ->param('functionId', '', new UID(), 'Function unique ID.', false) - ->param('variableId', '', new UID(), 'Variable unique ID.', false) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $functionId, string $variableId, Response $response, Database $dbForProject) { - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $variable = $dbForProject->getDocument('variables', $variableId); - if ( - $variable === false || - $variable->isEmpty() || - $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || - $variable->getAttribute('resourceType') !== 'function' - ) { - throw new Exception(Exception::VARIABLE_NOT_FOUND); - } - - if ($variable === false || $variable->isEmpty()) { - throw new Exception(Exception::VARIABLE_NOT_FOUND); - } - - $response->dynamic($variable, Response::MODEL_VARIABLE); - }); - -App::put('/v1/functions/:functionId/variables/:variableId') - ->desc('Update variable') - ->groups(['api', 'functions']) - ->label('scope', 'functions.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('audits.event', 'variable.update') - ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'updateVariable') - ->label('sdk.description', '/docs/references/functions/update-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) - ->param('functionId', '', new UID(), 'Function unique ID.', false) - ->param('variableId', '', new UID(), 'Variable unique ID.', false) - ->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false) - ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true) - ->inject('response') - ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (string $functionId, string $variableId, string $key, ?string $value, Response $response, Database $dbForProject, Database $dbForConsole) { - - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function') { - throw new Exception(Exception::VARIABLE_NOT_FOUND); - } - - if ($variable === false || $variable->isEmpty()) { - throw new Exception(Exception::VARIABLE_NOT_FOUND); - } - - $variable - ->setAttribute('key', $key) - ->setAttribute('value', $value ?? $variable->getAttribute('value')) - ->setAttribute('search', implode(' ', [$variableId, $function->getId(), $key, 'function'])); - - try { - $dbForProject->updateDocument('variables', $variable->getId(), $variable); - } catch (DuplicateException $th) { - throw new Exception(Exception::VARIABLE_ALREADY_EXISTS); - } - - $dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false)); - - // Inform scheduler to pull the latest changes - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); - $schedule - ->setAttribute('resourceUpdatedAt', DateTime::now()) - ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); - - $response->dynamic($variable, Response::MODEL_VARIABLE); - }); - -App::delete('/v1/functions/:functionId/variables/:variableId') - ->desc('Delete variable') - ->groups(['api', 'functions']) - ->label('scope', 'functions.write') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('audits.event', 'variable.delete') - ->label('audits.resource', 'function/{request.functionId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'deleteVariable') - ->label('sdk.description', '/docs/references/functions/delete-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) - ->param('functionId', '', new UID(), 'Function unique ID.', false) - ->param('variableId', '', new UID(), 'Variable unique ID.', false) - ->inject('response') - ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (string $functionId, string $variableId, Response $response, Database $dbForProject, Database $dbForConsole) { - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function') { - throw new Exception(Exception::VARIABLE_NOT_FOUND); - } - - if ($variable === false || $variable->isEmpty()) { - throw new Exception(Exception::VARIABLE_NOT_FOUND); - } - - $dbForProject->deleteDocument('variables', $variable->getId()); - - $dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false)); - - // Inform scheduler to pull the latest changes - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); - $schedule - ->setAttribute('resourceUpdatedAt', DateTime::now()) - ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); - - $response->noContent(); - }); - -App::get('/v1/functions/templates') - ->groups(['api']) - ->desc('List function templates') - ->label('scope', 'public') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'listTemplates') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.description', '/docs/references/functions/list-templates.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEMPLATE_FUNCTION_LIST) - ->param('runtimes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('runtimes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of runtimes allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' runtimes are allowed.', true) - ->param('useCases', [], new ArrayList(new WhiteList(['dev-tools','starter','databases','ai','messaging','utilities']), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) - ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) - ->param('offset', 0, new Range(0, 5000), 'Offset the list of returned templates. Maximum offset is 5000.', true) - ->inject('response') - ->action(function (array $runtimes, array $usecases, int $limit, int $offset, Response $response) { - $templates = Config::getParam('function-templates', []); - - if (!empty($runtimes)) { - $templates = \array_filter($templates, function ($template) use ($runtimes) { - return \count(\array_intersect($runtimes, \array_column($template['runtimes'], 'name'))) > 0; - }); - } - - if (!empty($usecases)) { - $templates = \array_filter($templates, function ($template) use ($usecases) { - return \count(\array_intersect($usecases, $template['useCases'])) > 0; - }); - } - - $responseTemplates = \array_slice($templates, $offset, $limit); - $response->dynamic(new Document([ - 'templates' => $responseTemplates, - 'total' => \count($responseTemplates), - ]), Response::MODEL_TEMPLATE_FUNCTION_LIST); - }); - -App::get('/v1/functions/templates/:templateId') - ->desc('Get function template') - ->label('scope', 'public') - ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getTemplate') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.description', '/docs/references/functions/get-template.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEMPLATE_FUNCTION) - ->param('templateId', '', new Text(128), 'Template ID.') - ->inject('response') - ->action(function (string $templateId, Response $response) { - $templates = Config::getParam('function-templates', []); - - $filtered = \array_filter($templates, function ($template) use ($templateId) { - return $template['id'] === $templateId; - }); - - $template = array_shift($filtered); - - if (empty($template)) { - throw new Exception(Exception::FUNCTION_TEMPLATE_NOT_FOUND); - } - - $response->dynamic(new Document($template), Response::MODEL_TEMPLATE_FUNCTION); - }); diff --git a/app/controllers/api/graphql.php b/app/controllers/api/graphql.php index f79f433b5c..72951b608e 100644 --- a/app/controllers/api/graphql.php +++ b/app/controllers/api/graphql.php @@ -5,6 +5,10 @@ use Appwrite\Extend\Exception; use Appwrite\Extend\Exception as AppwriteException; use Appwrite\GraphQL\Promises\Adapter; use Appwrite\GraphQL\Schema; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use GraphQL\Error\DebugFlag; @@ -38,13 +42,19 @@ App::get('/v1/graphql') ->desc('GraphQL endpoint') ->groups(['graphql']) ->label('scope', 'graphql') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'graphql') - ->label('sdk.hide', true) - ->label('sdk.description', '/docs/references/graphql/get.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ANY) + ->label('sdk', new Method( + namespace: 'graphql', + name: 'get', + auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], + hide: true, + description: '/docs/references/graphql/get.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ANY, + ) + ] + )) ->label('abuse-limit', 60) ->label('abuse-time', 60) ->param('query', '', new Text(0, 0), 'The query to execute.') @@ -78,17 +88,22 @@ App::post('/v1/graphql/mutation') ->desc('GraphQL endpoint') ->groups(['graphql']) ->label('scope', 'graphql') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'graphql') - ->label('sdk.method', 'mutation') - ->label('sdk.methodType', 'graphql') - ->label('sdk.description', '/docs/references/graphql/post.md') - ->label('sdk.parameters', [ - 'query' => ['default' => [], 'validator' => new JSON(), 'description' => 'The query or queries to execute.', 'optional' => false], - ]) - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ANY) + ->label('sdk', new Method( + namespace: 'graphql', + name: 'mutation', + auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], + description: '/docs/references/graphql/post.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ANY, + ) + ], + type: MethodType::GRAPHQL, + additionalParameters: [ + 'query' => ['default' => [], 'validator' => new JSON(), 'description' => 'The query or queries to execute.', 'optional' => false], + ], + )) ->label('abuse-limit', 60) ->label('abuse-time', 60) ->inject('request') @@ -123,17 +138,22 @@ App::post('/v1/graphql') ->desc('GraphQL endpoint') ->groups(['graphql']) ->label('scope', 'graphql') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'graphql') - ->label('sdk.method', 'query') - ->label('sdk.methodType', 'graphql') - ->label('sdk.description', '/docs/references/graphql/post.md') - ->label('sdk.parameters', [ - 'query' => ['default' => [], 'validator' => new JSON(), 'description' => 'The query or queries to execute.', 'optional' => false], - ]) - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_ANY) + ->label('sdk', new Method( + namespace: 'graphql', + name: 'query', + auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], + description: '/docs/references/graphql/post.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ANY, + ) + ], + type: MethodType::GRAPHQL, + additionalParameters: [ + 'query' => ['default' => [], 'validator' => new JSON(), 'description' => 'The query or queries to execute.', 'optional' => false], + ], + )) ->label('abuse-limit', 60) ->label('abuse-time', 60) ->inject('request') diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 60a8c0ca97..94ec2059c9 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -3,14 +3,18 @@ use Appwrite\ClamAV\Network; use Appwrite\Event\Event; use Appwrite\Extend\Exception; +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\Config\Config; use Utopia\Database\Document; use Utopia\Domains\Validator\PublicDomain; use Utopia\Pools\Group; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; +use Utopia\Queue\Queue; use Utopia\Registry\Registry; use Utopia\Storage\Device; use Utopia\Storage\Device\Local; @@ -26,13 +30,19 @@ App::get('/v1/health') ->desc('Get HTTP') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/health/get.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + namespace: 'health', + name: 'get', + auth: [AuthType::KEY], + description: '/docs/references/health/get.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->action(function (Response $response) { @@ -49,9 +59,6 @@ App::get('/v1/health/version') ->desc('Get version') ->groups(['api', 'health']) ->label('scope', 'public') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_VERSION) ->inject('response') ->action(function (Response $response) { $response->dynamic(new Document([ 'version' => APP_VERSION_STABLE ]), Response::MODEL_HEALTH_VERSION); @@ -61,13 +68,19 @@ App::get('/v1/health/db') ->desc('Get DB') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getDB') - ->label('sdk.description', '/docs/references/health/get-db.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getDB', + description: '/docs/references/health/get-db.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { @@ -115,13 +128,19 @@ App::get('/v1/health/cache') ->desc('Get cache') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getCache') - ->label('sdk.description', '/docs/references/health/get-cache.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getCache', + description: '/docs/references/health/get-cache.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { @@ -169,74 +188,23 @@ App::get('/v1/health/cache') ]), Response::MODEL_HEALTH_STATUS_LIST); }); -App::get('/v1/health/queue') - ->desc('Get queue') - ->groups(['api', 'health']) - ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueue') - ->label('sdk.description', '/docs/references/health/get-queue.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) - ->inject('response') - ->inject('pools') - ->action(function (Response $response, Group $pools) { - - $output = []; - - $configs = [ - 'Queue' => Config::getParam('pools-queue'), - ]; - - foreach ($configs as $key => $config) { - foreach ($config as $database) { - $checkStart = \microtime(true); - try { - /** @var Connection $adapter */ - $adapter = $pools->get($database)->pop()->getResource(); - - if ($adapter->ping()) { - $output[] = new Document([ - 'name' => $key . " ($database)", - 'status' => 'pass', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) - ]); - } else { - $output[] = new Document([ - 'name' => $key . " ($database)", - 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) - ]); - } - } catch (\Throwable $th) { - $output[] = new Document([ - 'name' => $key . " ($database)", - 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) - ]); - } - } - } - - $response->dynamic(new Document([ - 'statuses' => $output, - 'total' => count($output), - ]), Response::MODEL_HEALTH_STATUS_LIST); - }); - App::get('/v1/health/pubsub') ->desc('Get pubsub') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getPubSub') - ->label('sdk.description', '/docs/references/health/get-pubsub.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getPubSub', + description: '/docs/references/health/get-pubsub.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { @@ -288,13 +256,19 @@ App::get('/v1/health/time') ->desc('Get time') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getTime') - ->label('sdk.description', '/docs/references/health/get-time.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_TIME) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getTime', + description: '/docs/references/health/get-time.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_TIME, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->action(function (Response $response) { @@ -345,21 +319,26 @@ App::get('/v1/health/queue/webhooks') ->desc('Get webhooks queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueWebhooks') - ->label('sdk.description', '/docs/references/health/get-queue-webhooks.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueWebhooks', + description: '/docs/references/health/get-queue-webhooks.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::WEBHOOK_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::WEBHOOK_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -372,21 +351,26 @@ App::get('/v1/health/queue/logs') ->desc('Get logs queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueLogs') - ->label('sdk.description', '/docs/references/health/get-queue-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueLogs', + description: '/docs/references/health/get-queue-logs.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::AUDITS_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::AUDITS_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -399,13 +383,19 @@ App::get('/v1/health/certificate') ->desc('Get the SSL certificate for a domain') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getCertificate') - ->label('sdk.description', '/docs/references/health/get-certificate.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_CERTIFICATE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getCertificate', + description: '/docs/references/health/get-certificate.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_CERTIFICATE, + ) + ], + contentType: ContentType::JSON + )) ->param('domain', null, new Multiple([new Domain(), new PublicDomain()]), Multiple::TYPE_STRING, 'Domain name') ->inject('response') ->action(function (string $domain, Response $response) { @@ -449,21 +439,26 @@ App::get('/v1/health/queue/certificates') ->desc('Get certificates queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueCertificates') - ->label('sdk.description', '/docs/references/health/get-queue-certificates.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueCertificates', + description: '/docs/references/health/get-queue-certificates.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::CERTIFICATES_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::CERTIFICATES_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -476,21 +471,26 @@ App::get('/v1/health/queue/builds') ->desc('Get builds queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueBuilds') - ->label('sdk.description', '/docs/references/health/get-queue-builds.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueBuilds', + description: '/docs/references/health/get-queue-builds.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::BUILDS_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::BUILDS_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -503,22 +503,27 @@ App::get('/v1/health/queue/databases') ->desc('Get databases queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueDatabases') - ->label('sdk.description', '/docs/references/health/get-queue-databases.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueDatabases', + description: '/docs/references/health/get-queue-databases.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('name', 'database_db_main', new Text(256), 'Queue name for which to check the queue size', true) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (string $name, int|string $threshold, Connection $queue, Response $response) { + ->action(function (string $name, int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client($name, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue($name)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -531,21 +536,26 @@ App::get('/v1/health/queue/deletes') ->desc('Get deletes queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueDeletes') - ->label('sdk.description', '/docs/references/health/get-queue-deletes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueDeletes', + description: '/docs/references/health/get-queue-deletes.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::DELETE_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::DELETE_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -558,21 +568,26 @@ App::get('/v1/health/queue/mails') ->desc('Get mails queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueMails') - ->label('sdk.description', '/docs/references/health/get-queue-mails.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueMails', + description: '/docs/references/health/get-queue-mails.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::MAILS_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::MAILS_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -585,21 +600,26 @@ App::get('/v1/health/queue/messaging') ->desc('Get messaging queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueMessaging') - ->label('sdk.description', '/docs/references/health/get-queue-messaging.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueMessaging', + description: '/docs/references/health/get-queue-messaging.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::MESSAGING_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::MESSAGING_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -612,21 +632,26 @@ App::get('/v1/health/queue/migrations') ->desc('Get migrations queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueMigrations') - ->label('sdk.description', '/docs/references/health/get-queue-migrations.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueMigrations', + description: '/docs/references/health/get-queue-migrations.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::MIGRATIONS_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::MIGRATIONS_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -639,21 +664,26 @@ App::get('/v1/health/queue/functions') ->desc('Get functions queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueFunctions') - ->label('sdk.description', '/docs/references/health/get-queue-functions.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueFunctions', + description: '/docs/references/health/get-queue-functions.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::FUNCTIONS_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::FUNCTIONS_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -662,25 +692,30 @@ App::get('/v1/health/queue/functions') $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); }, ['response']); -App::get('/v1/health/queue/usage') - ->desc('Get usage queue') +App::get('/v1/health/queue/stats-resources') + ->desc('Get stats resources queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueUsage') - ->label('sdk.description', '/docs/references/health/get-queue-usage.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueStatsResources', + description: '/docs/references/health/get-queue-stats-resources.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::USAGE_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::STATS_RESOURCES_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -689,25 +724,62 @@ App::get('/v1/health/queue/usage') $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); }); -App::get('/v1/health/queue/usage-dump') +App::get('/v1/health/queue/stats-usage') + ->desc('Get stats usage queue') + ->groups(['api', 'health']) + ->label('scope', 'health.read') + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueUsage', + description: '/docs/references/health/get-queue-stats-usage.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) + ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) + ->inject('publisher') + ->inject('response') + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { + $threshold = \intval($threshold); + + $size = $publisher->getQueueSize(new Queue(Event::STATS_USAGE_QUEUE_NAME)); + + if ($size >= $threshold) { + throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); + } + + $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); + }); + +App::get('/v1/health/queue/stats-usage-dump') ->desc('Get usage dump queue') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getQueueUsageDump') - ->label('sdk.description', '/docs/references/health/get-queue-usage-dump.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getQueueStatsUsageDump', + description: '/docs/references/health/get-queue-stats-usage-dump.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->inject('queue') + ->inject('publisher') ->inject('response') - ->action(function (int|string $threshold, Connection $queue, Response $response) { + ->action(function (int|string $threshold, Publisher $publisher, Response $response) { $threshold = \intval($threshold); - $client = new Client(Event::USAGE_DUMP_QUEUE_NAME, $queue); - $size = $client->getQueueSize(); + $size = $publisher->getQueueSize(new Queue(Event::STATS_USAGE_DUMP_QUEUE_NAME)); if ($size >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue size threshold hit. Current size is {$size} and threshold is {$threshold}."); @@ -720,13 +792,19 @@ App::get('/v1/health/storage/local') ->desc('Get local storage') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getStorageLocal') - ->label('sdk.description', '/docs/references/health/get-storage-local.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getStorageLocal', + description: '/docs/references/health/get-storage-local.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->action(function (Response $response) { @@ -763,19 +841,26 @@ App::get('/v1/health/storage') ->desc('Get storage') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getStorage') - ->label('sdk.description', '/docs/references/health/get-storage.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_STATUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getStorage', + description: '/docs/references/health/get-storage.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_STATUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->inject('deviceForFiles') ->inject('deviceForFunctions') + ->inject('deviceForSites') ->inject('deviceForBuilds') - ->action(function (Response $response, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds) { - $devices = [$deviceForFiles, $deviceForFunctions, $deviceForBuilds]; + ->action(function (Response $response, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForSites, Device $deviceForBuilds) { + $devices = [$deviceForFiles, $deviceForFunctions, $deviceForSites, $deviceForBuilds]; $checkStart = \microtime(true); foreach ($devices as $device) { @@ -804,13 +889,19 @@ App::get('/v1/health/anti-virus') ->desc('Get antivirus') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getAntivirus') - ->label('sdk.description', '/docs/references/health/get-storage-anti-virus.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_ANTIVIRUS) + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getAntivirus', + description: '/docs/references/health/get-storage-anti-virus.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_ANTIVIRUS, + ) + ], + contentType: ContentType::JSON + )) ->inject('response') ->action(function (Response $response) { @@ -843,17 +934,28 @@ App::get('/v1/health/queue/failed/:name') ->desc('Get number of failed queue jobs') ->groups(['api', 'health']) ->label('scope', 'health.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'health') - ->label('sdk.method', 'getFailedJobs') + ->label('sdk', new Method( + auth: [AuthType::KEY], + namespace: 'health', + name: 'getFailedJobs', + description: '/docs/references/health/get-failed-queue-jobs.md', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_HEALTH_QUEUE, + ) + ], + contentType: ContentType::JSON + )) ->param('name', '', new WhiteList([ Event::DATABASE_QUEUE_NAME, Event::DELETE_QUEUE_NAME, Event::AUDITS_QUEUE_NAME, Event::MAILS_QUEUE_NAME, Event::FUNCTIONS_QUEUE_NAME, - Event::USAGE_QUEUE_NAME, - Event::USAGE_DUMP_QUEUE_NAME, + Event::STATS_RESOURCES_QUEUE_NAME, + Event::STATS_USAGE_QUEUE_NAME, + Event::STATS_USAGE_DUMP_QUEUE_NAME, Event::WEBHOOK_QUEUE_NAME, Event::CERTIFICATES_QUEUE_NAME, Event::BUILDS_QUEUE_NAME, @@ -861,17 +963,12 @@ App::get('/v1/health/queue/failed/:name') Event::MIGRATIONS_QUEUE_NAME ]), 'The name of the queue') ->param('threshold', 5000, new Integer(true), 'Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.', true) - ->label('sdk.description', '/docs/references/health/get-failed-queue-jobs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_HEALTH_QUEUE) ->inject('response') - ->inject('queue') - ->action(function (string $name, int|string $threshold, Response $response, Connection $queue) { + ->inject('publisher') + ->action(function (string $name, int|string $threshold, Response $response, Publisher $publisher) { $threshold = \intval($threshold); - $client = new Client($name, $queue); - $failed = $client->countFailedJobs(); + $failed = $publisher->getQueueSize(new Queue($name), failedJobs: true); if ($failed >= $threshold) { throw new Exception(Exception::HEALTH_QUEUE_SIZE_EXCEEDED, "Queue failed jobs threshold hit. Current size is {$failed} and threshold is {$threshold}."); diff --git a/app/controllers/api/locale.php b/app/controllers/api/locale.php index 1f042d2239..523ac3976b 100644 --- a/app/controllers/api/locale.php +++ b/app/controllers/api/locale.php @@ -1,5 +1,8 @@ <?php +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use MaxMind\Db\Reader; @@ -12,15 +15,18 @@ App::get('/v1/locale') ->desc('Get user locale') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/locale/get-locale.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOCALE) - ->label('sdk.offline.model', '/localed') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'locale', + name: 'get', + description: '/docs/references/locale/get-locale.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOCALE, + ) + ] + )) ->inject('request') ->inject('response') ->inject('locale') @@ -72,15 +78,18 @@ App::get('/v1/locale/codes') ->desc('List locale codes') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listCodes') - ->label('sdk.description', '/docs/references/locale/list-locale-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOCALE_CODE_LIST) - ->label('sdk.offline.model', '/locale/localeCode') - ->label('sdk.offline.key', 'current') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listCodes', + description: '/docs/references/locale/list-locale-codes.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOCALE_CODE_LIST, + ) + ] + )) ->inject('response') ->action(function (Response $response) { $codes = Config::getParam('locale-codes'); @@ -94,19 +103,22 @@ App::get('/v1/locale/countries') ->desc('List countries') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listCountries') - ->label('sdk.description', '/docs/references/locale/list-countries.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COUNTRY_LIST) - ->label('sdk.offline.model', '/locale/countries') - ->label('sdk.offline.response.key', 'code') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listCountries', + description: '/docs/references/locale/list-countries.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_COUNTRY_LIST, + ) + ] + )) ->inject('response') ->inject('locale') ->action(function (Response $response, Locale $locale) { - $list = Config::getParam('locale-countries'); /* @var $list array */ + $list = array_keys(Config::getParam('locale-countries')); /* @var $list array */ $output = []; foreach ($list as $value) { @@ -127,15 +139,18 @@ App::get('/v1/locale/countries/eu') ->desc('List EU countries') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listCountriesEU') - ->label('sdk.description', '/docs/references/locale/list-countries-eu.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_COUNTRY_LIST) - ->label('sdk.offline.model', '/locale/countries/eu') - ->label('sdk.offline.response.key', 'code') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listCountriesEU', + description: '/docs/references/locale/list-countries-eu.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_COUNTRY_LIST, + ) + ] + )) ->inject('response') ->inject('locale') ->action(function (Response $response, Locale $locale) { @@ -162,15 +177,18 @@ App::get('/v1/locale/countries/phones') ->desc('List countries phone codes') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listCountriesPhones') - ->label('sdk.description', '/docs/references/locale/list-countries-phones.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PHONE_LIST) - ->label('sdk.offline.model', '/locale/countries/phones') - ->label('sdk.offline.response.key', 'countryCode') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listCountriesPhones', + description: '/docs/references/locale/list-countries-phones.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PHONE_LIST, + ) + ] + )) ->inject('response') ->inject('locale') ->action(function (Response $response, Locale $locale) { @@ -196,19 +214,22 @@ App::get('/v1/locale/continents') ->desc('List continents') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listContinents') - ->label('sdk.description', '/docs/references/locale/list-continents.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_CONTINENT_LIST) - ->label('sdk.offline.model', '/locale/continents') - ->label('sdk.offline.response.key', 'code') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listContinents', + description: '/docs/references/locale/list-continents.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_CONTINENT_LIST, + ) + ] + )) ->inject('response') ->inject('locale') ->action(function (Response $response, Locale $locale) { - $list = Config::getParam('locale-continents'); + $list = array_keys(Config::getParam('locale-continents')); foreach ($list as $value) { $output[] = new Document([ @@ -228,15 +249,18 @@ App::get('/v1/locale/currencies') ->desc('List currencies') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listCurrencies') - ->label('sdk.description', '/docs/references/locale/list-currencies.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_CURRENCY_LIST) - ->label('sdk.offline.model', '/locale/currencies') - ->label('sdk.offline.response.key', 'code') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listCurrencies', + description: '/docs/references/locale/list-currencies.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_CURRENCY_LIST, + ) + ] + )) ->inject('response') ->action(function (Response $response) { $list = Config::getParam('locale-currencies'); @@ -251,15 +275,18 @@ App::get('/v1/locale/languages') ->desc('List languages') ->groups(['api', 'locale']) ->label('scope', 'locale.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'locale') - ->label('sdk.method', 'listLanguages') - ->label('sdk.description', '/docs/references/locale/list-languages.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LANGUAGE_LIST) - ->label('sdk.offline.model', '/locale/languages') - ->label('sdk.offline.response.key', 'code') + ->label('sdk', new Method( + namespace: 'locale', + name: 'listLanguages', + description: '/docs/references/locale/list-languages.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LANGUAGE_LIST, + ) + ] + )) ->inject('response') ->action(function (Response $response) { $list = Config::getParam('locale-languages'); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index e4a627d027..178266db60 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -11,6 +11,10 @@ use Appwrite\Messaging\Status as MessageStatus; use Appwrite\Network\Validator\Email; use Appwrite\Permission; use Appwrite\Role; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CompoundUID; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Messages; @@ -57,13 +61,18 @@ App::post('/v1/messaging/providers/mailgun') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createMailgunProvider') - ->label('sdk.description', '/docs/references/messaging/create-mailgun-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createMailgunProvider', + description: '/docs/references/messaging/create-mailgun-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) @@ -145,13 +154,18 @@ App::post('/v1/messaging/providers/sendgrid') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createSendgridProvider') - ->label('sdk.description', '/docs/references/messaging/create-sendgrid-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createSendgridProvider', + description: '/docs/references/messaging/create-sendgrid-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Provider name.') ->param('apiKey', '', new Text(0), 'Sendgrid API key.', true) @@ -221,13 +235,18 @@ App::post('/v1/messaging/providers/smtp') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createSmtpProvider') - ->label('sdk.description', '/docs/references/messaging/create-smtp-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createSmtpProvider', + description: '/docs/references/messaging/create-smtp-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Provider name.') ->param('host', '', new Text(0), '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.') @@ -310,13 +329,18 @@ App::post('/v1/messaging/providers/msg91') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) ->label('event', 'providers.[providerId].create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createMsg91Provider') - ->label('sdk.description', '/docs/references/messaging/create-msg91-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createMsg91Provider', + description: '/docs/references/messaging/create-msg91-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Provider name.') ->param('templateId', '', new Text(0), 'Msg91 template ID', true) @@ -387,13 +411,18 @@ App::post('/v1/messaging/providers/telesign') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createTelesignProvider') - ->label('sdk.description', '/docs/references/messaging/create-telesign-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createTelesignProvider', + description: '/docs/references/messaging/create-telesign-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Provider name.') ->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) @@ -465,13 +494,18 @@ App::post('/v1/messaging/providers/textmagic') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createTextmagicProvider') - ->label('sdk.description', '/docs/references/messaging/create-textmagic-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createTextmagicProvider', + description: '/docs/references/messaging/create-textmagic-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Provider name.') ->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) @@ -543,13 +577,18 @@ App::post('/v1/messaging/providers/twilio') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createTwilioProvider') - ->label('sdk.description', '/docs/references/messaging/create-twilio-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createTwilioProvider', + description: '/docs/references/messaging/create-twilio-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Provider name.') ->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) @@ -621,13 +660,18 @@ App::post('/v1/messaging/providers/vonage') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createVonageProvider') - ->label('sdk.description', '/docs/references/messaging/create-vonage-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createVonageProvider', + description: '/docs/references/messaging/create-vonage-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Provider name.') ->param('from', '', new Phone(), 'Sender Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) @@ -699,13 +743,18 @@ App::post('/v1/messaging/providers/fcm') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createFcmProvider') - ->label('sdk.description', '/docs/references/messaging/create-fcm-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createFcmProvider', + description: '/docs/references/messaging/create-fcm-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Provider name.') ->param('serviceAccountJSON', null, new JSON(), 'FCM service account JSON.', true) @@ -763,13 +812,18 @@ App::post('/v1/messaging/providers/apns') ->label('event', 'providers.[providerId].create') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createApnsProvider') - ->label('sdk.description', '/docs/references/messaging/create-apns-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createApnsProvider', + description: '/docs/references/messaging/create-apns-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Provider name.') ->param('authKey', '', new Text(0), 'APNS authentication key.', true) @@ -847,13 +901,18 @@ App::get('/v1/messaging/providers') ->groups(['api', 'messaging']) ->label('scope', 'providers.read') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listProviders') - ->label('sdk.description', '/docs/references/messaging/list-providers.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listProviders', + description: '/docs/references/messaging/list-providers.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER_LIST, + ) + ] + )) ->param('queries', [], new Providers(), '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(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('dbForProject') @@ -904,13 +963,18 @@ App::get('/v1/messaging/providers/:providerId/logs') ->groups(['api', 'messaging']) ->label('scope', 'providers.read') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listProviderLogs') - ->label('sdk.description', '/docs/references/messaging/list-provider-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listProviderLogs', + description: '/docs/references/messaging/list-provider-logs.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), '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', true) ->inject('response') @@ -930,13 +994,15 @@ App::get('/v1/messaging/providers/:providerId/logs') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $grouped = Query::groupByType($queries); - $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; - $offset = $grouped['offset'] ?? 0; + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); $audit = new Audit($dbForProject); $resource = 'provider/' . $providerId; - $logs = $audit->getLogsByResource($resource, $limit, $offset); + $logs = $audit->getLogsByResource($resource, $queries); $output = []; foreach ($logs as $i => &$log) { @@ -983,7 +1049,7 @@ App::get('/v1/messaging/providers/:providerId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource), + 'total' => $audit->countLogsByResource($resource, $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -993,13 +1059,18 @@ App::get('/v1/messaging/providers/:providerId') ->groups(['api', 'messaging']) ->label('scope', 'providers.read') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'getProvider') - ->label('sdk.description', '/docs/references/messaging/get-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'getProvider', + description: '/docs/references/messaging/get-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->inject('dbForProject') ->inject('response') @@ -1021,13 +1092,18 @@ App::patch('/v1/messaging/providers/mailgun/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateMailgunProvider') - ->label('sdk.description', '/docs/references/messaging/update-mailgun-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateMailgunProvider', + description: '/docs/references/messaging/update-mailgun-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('apiKey', '', new Text(0), 'Mailgun API Key.', true) @@ -1128,13 +1204,18 @@ App::patch('/v1/messaging/providers/sendgrid/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateSendgridProvider') - ->label('sdk.description', '/docs/references/messaging/update-sendgrid-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateSendgridProvider', + description: '/docs/references/messaging/update-sendgrid-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1220,13 +1301,18 @@ App::patch('/v1/messaging/providers/smtp/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateSmtpProvider') - ->label('sdk.description', '/docs/references/messaging/update-smtp-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateSmtpProvider', + description: '/docs/references/messaging/update-smtp-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('host', '', new Text(0), '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.', true) @@ -1343,13 +1429,18 @@ App::patch('/v1/messaging/providers/msg91/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateMsg91Provider') - ->label('sdk.description', '/docs/references/messaging/update-msg91-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateMsg91Provider', + description: '/docs/references/messaging/update-msg91-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1424,13 +1515,18 @@ App::patch('/v1/messaging/providers/telesign/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateTelesignProvider') - ->label('sdk.description', '/docs/references/messaging/update-telesign-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateTelesignProvider', + description: '/docs/references/messaging/update-telesign-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1507,13 +1603,18 @@ App::patch('/v1/messaging/providers/textmagic/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateTextmagicProvider') - ->label('sdk.description', '/docs/references/messaging/update-textmagic-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateTextmagicProvider', + description: '/docs/references/messaging/update-textmagic-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1590,13 +1691,18 @@ App::patch('/v1/messaging/providers/twilio/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateTwilioProvider') - ->label('sdk.description', '/docs/references/messaging/update-twilio-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateTwilioProvider', + description: '/docs/references/messaging/update-twilio-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1673,13 +1779,18 @@ App::patch('/v1/messaging/providers/vonage/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateVonageProvider') - ->label('sdk.description', '/docs/references/messaging/update-vonage-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateVonageProvider', + description: '/docs/references/messaging/update-vonage-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1756,13 +1867,18 @@ App::patch('/v1/messaging/providers/fcm/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateFcmProvider') - ->label('sdk.description', '/docs/references/messaging/update-fcm-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateFcmProvider', + description: '/docs/references/messaging/update-fcm-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1826,13 +1942,18 @@ App::patch('/v1/messaging/providers/apns/:providerId') ->label('event', 'providers.[providerId].update') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateApnsProvider') - ->label('sdk.description', '/docs/references/messaging/update-apns-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateApnsProvider', + description: '/docs/references/messaging/update-apns-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER, + ) + ] + )) ->param('providerId', '', new UID(), 'Provider ID.') ->param('name', '', new Text(128), 'Provider name.', true) ->param('enabled', null, new Boolean(), 'Set as enabled.', true) @@ -1922,13 +2043,19 @@ App::delete('/v1/messaging/providers/:providerId') ->label('event', 'providers.[providerId].delete') ->label('scope', 'providers.write') ->label('resourceType', RESOURCE_TYPE_PROVIDERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'deleteProvider') - ->label('sdk.description', '/docs/references/messaging/delete-provider.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'deleteProvider', + description: '/docs/references/messaging/delete-provider.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('providerId', '', new UID(), 'Provider ID.') ->inject('queueForEvents') ->inject('dbForProject') @@ -1958,13 +2085,18 @@ App::post('/v1/messaging/topics') ->label('event', 'topics.[topicId].create') ->label('scope', 'topics.write') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createTopic') - ->label('sdk.description', '/docs/references/messaging/create-topic.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOPIC) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createTopic', + description: '/docs/references/messaging/create-topic.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOPIC, + ) + ] + )) ->param('topicId', '', new CustomId(), 'Topic ID. Choose a custom Topic ID or a new Topic ID.') ->param('name', '', new Text(128), 'Topic Name.') ->param('subscribe', [Role::users()], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), '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 ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) @@ -1999,13 +2131,18 @@ App::get('/v1/messaging/topics') ->groups(['api', 'messaging']) ->label('scope', 'topics.read') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listTopics') - ->label('sdk.description', '/docs/references/messaging/list-topics.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOPIC_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listTopics', + description: '/docs/references/messaging/list-topics.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOPIC_LIST, + ) + ] + )) ->param('queries', [], new Topics(), '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(', ', Topics::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('dbForProject') @@ -2056,13 +2193,18 @@ App::get('/v1/messaging/topics/:topicId/logs') ->groups(['api', 'messaging']) ->label('scope', 'topics.read') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listTopicLogs') - ->label('sdk.description', '/docs/references/messaging/list-topic-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listTopicLogs', + description: '/docs/references/messaging/list-topic-logs.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ] + )) ->param('topicId', '', new UID(), 'Topic ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), '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', true) ->inject('response') @@ -2082,13 +2224,15 @@ App::get('/v1/messaging/topics/:topicId/logs') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $grouped = Query::groupByType($queries); - $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; - $offset = $grouped['offset'] ?? 0; + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); $audit = new Audit($dbForProject); $resource = 'topic/' . $topicId; - $logs = $audit->getLogsByResource($resource, $limit, $offset); + $logs = $audit->getLogsByResource($resource, $queries); $output = []; @@ -2136,7 +2280,7 @@ App::get('/v1/messaging/topics/:topicId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource), + 'total' => $audit->countLogsByResource($resource, $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -2146,13 +2290,18 @@ App::get('/v1/messaging/topics/:topicId') ->groups(['api', 'messaging']) ->label('scope', 'topics.read') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'getTopic') - ->label('sdk.description', '/docs/references/messaging/get-topic.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOPIC) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'getTopic', + description: '/docs/references/messaging/get-topic.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOPIC, + ) + ] + )) ->param('topicId', '', new UID(), 'Topic ID.') ->inject('dbForProject') ->inject('response') @@ -2175,13 +2324,18 @@ App::patch('/v1/messaging/topics/:topicId') ->label('event', 'topics.[topicId].update') ->label('scope', 'topics.write') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateTopic') - ->label('sdk.description', '/docs/references/messaging/update-topic.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOPIC) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateTopic', + description: '/docs/references/messaging/update-topic.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TOPIC, + ) + ] + )) ->param('topicId', '', new UID(), 'Topic ID.') ->param('name', null, new Text(128), 'Topic Name.', true) ->param('subscribe', null, new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), '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 ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) @@ -2220,13 +2374,19 @@ App::delete('/v1/messaging/topics/:topicId') ->label('event', 'topics.[topicId].delete') ->label('scope', 'topics.write') ->label('resourceType', RESOURCE_TYPE_TOPICS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'deleteTopic') - ->label('sdk.description', '/docs/references/messaging/delete-topic.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'deleteTopic', + description: '/docs/references/messaging/delete-topic.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('topicId', '', new UID(), 'Topic ID.') ->inject('queueForEvents') ->inject('dbForProject') @@ -2261,13 +2421,18 @@ App::post('/v1/messaging/topics/:topicId/subscribers') ->label('event', 'topics.[topicId].subscribers.[subscriberId].create') ->label('scope', 'subscribers.write') ->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS) - ->label('sdk.auth', [APP_AUTH_TYPE_JWT, APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createSubscriber') - ->label('sdk.description', '/docs/references/messaging/create-subscriber.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SUBSCRIBER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createSubscriber', + description: '/docs/references/messaging/create-subscriber.md', + auth: [AuthType::JWT, AuthType::SESSION, AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SUBSCRIBER, + ) + ] + )) ->param('subscriberId', '', new CustomId(), 'Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.') ->param('topicId', '', new UID(), 'Topic ID. The topic ID to subscribe to.') ->param('targetId', '', new UID(), 'Target ID. The target ID to link to the specified Topic ID.') @@ -2355,13 +2520,18 @@ App::get('/v1/messaging/topics/:topicId/subscribers') ->groups(['api', 'messaging']) ->label('scope', 'subscribers.read') ->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listSubscribers') - ->label('sdk.description', '/docs/references/messaging/list-subscribers.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SUBSCRIBER_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listSubscribers', + description: '/docs/references/messaging/list-subscribers.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SUBSCRIBER_LIST, + ) + ] + )) ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('queries', [], new Subscribers(), '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(', ', Providers::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) @@ -2435,13 +2605,18 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs') ->groups(['api', 'messaging']) ->label('scope', 'subscribers.read') ->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listSubscriberLogs') - ->label('sdk.description', '/docs/references/messaging/list-subscriber-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listSubscriberLogs', + description: '/docs/references/messaging/list-subscriber-logs.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ] + )) ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), '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', true) ->inject('response') @@ -2461,13 +2636,15 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $grouped = Query::groupByType($queries); - $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; - $offset = $grouped['offset'] ?? 0; + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); $audit = new Audit($dbForProject); $resource = 'subscriber/' . $subscriberId; - $logs = $audit->getLogsByResource($resource, $limit, $offset); + $logs = $audit->getLogsByResource($resource, $queries); $output = []; @@ -2515,7 +2692,7 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource), + 'total' => $audit->countLogsByResource($resource, $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -2525,13 +2702,18 @@ App::get('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->groups(['api', 'messaging']) ->label('scope', 'subscribers.read') ->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'getSubscriber') - ->label('sdk.description', '/docs/references/messaging/get-subscriber.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SUBSCRIBER) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'getSubscriber', + description: '/docs/references/messaging/get-subscriber.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SUBSCRIBER, + ) + ] + )) ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('dbForProject') @@ -2568,13 +2750,19 @@ App::delete('/v1/messaging/topics/:topicId/subscribers/:subscriberId') ->label('event', 'topics.[topicId].subscribers.[subscriberId].delete') ->label('scope', 'subscribers.write') ->label('resourceType', RESOURCE_TYPE_SUBSCRIBERS) - ->label('sdk.auth', [APP_AUTH_TYPE_JWT, APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'deleteSubscriber') - ->label('sdk.description', '/docs/references/messaging/delete-subscriber.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'deleteSubscriber', + description: '/docs/references/messaging/delete-subscriber.md', + auth: [AuthType::JWT, AuthType::SESSION, AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('topicId', '', new UID(), 'Topic ID. The topic ID subscribed to.') ->param('subscriberId', '', new UID(), 'Subscriber ID.') ->inject('queueForEvents') @@ -2628,13 +2816,18 @@ App::post('/v1/messaging/messages/email') ->label('event', 'messages.[messageId].create') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createEmail') - ->label('sdk.description', '/docs/references/messaging/create-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createEmail', + description: '/docs/references/messaging/create-email.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new CustomId(), '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.') ->param('subject', '', new Text(998), 'Email Subject.') ->param('content', '', new Text(64230), 'Email Content.') @@ -2649,11 +2842,11 @@ App::post('/v1/messaging/messages/email') ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), '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.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, string $subject, string $content, array $topics, array $users, array $targets, array $cc, array $bcc, array $attachments, bool $draft, bool $html, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $subject, string $content, array $topics, array $users, array $targets, array $cc, array $bcc, array $attachments, bool $draft, bool $html, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; @@ -2742,8 +2935,8 @@ App::post('/v1/messaging/messages/email') ->setMessageId($message->getId()); break; case MessageStatus::SCHEDULED: - $schedule = $dbForConsole->createDocument('schedules', new Document([ - 'region' => System::getEnv('_APP_REGION', 'default'), + $schedule = $dbForPlatform->createDocument('schedules', new Document([ + 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), 'resourceInternalId' => $message->getInternalId(), @@ -2781,13 +2974,18 @@ App::post('/v1/messaging/messages/sms') ->label('event', 'messages.[messageId].create') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createSms') - ->label('sdk.description', '/docs/references/messaging/create-sms.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createSms', + description: '/docs/references/messaging/create-sms.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new CustomId(), '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.') ->param('content', '', new Text(64230), 'SMS Content.') ->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true) @@ -2797,11 +2995,11 @@ App::post('/v1/messaging/messages/sms') ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), '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.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, string $content, array $topics, array $users, array $targets, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $content, array $topics, array $users, array $targets, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; @@ -2859,8 +3057,8 @@ App::post('/v1/messaging/messages/sms') ->setMessageId($message->getId()); break; case MessageStatus::SCHEDULED: - $schedule = $dbForConsole->createDocument('schedules', new Document([ - 'region' => System::getEnv('_APP_REGION', 'default'), + $schedule = $dbForPlatform->createDocument('schedules', new Document([ + 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), 'resourceInternalId' => $message->getInternalId(), @@ -2898,36 +3096,44 @@ App::post('/v1/messaging/messages/push') ->label('event', 'messages.[messageId].create') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'createPush') - ->label('sdk.description', '/docs/references/messaging/create-push.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'createPush', + description: '/docs/references/messaging/create-push.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new CustomId(), '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.') - ->param('title', '', new Text(256), 'Title for push notification.') - ->param('body', '', new Text(64230), 'Body for push notification.') + ->param('title', '', new Text(256), 'Title for push notification.', true) + ->param('body', '', new Text(64230), 'Body for push notification.', true) ->param('topics', [], new ArrayList(new UID()), 'List of Topic IDs.', true) ->param('users', [], new ArrayList(new UID()), 'List of User IDs.', true) ->param('targets', [], new ArrayList(new UID()), 'List of Targets IDs.', true) - ->param('data', null, new JSON(), 'Additional Data for push notification.', true) + ->param('data', null, new JSON(), 'Additional key-value pair data for push notification.', true) ->param('action', '', new Text(256), 'Action for push notification.', true) ->param('image', '', new CompoundUID(), '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>.', true) ->param('icon', '', new Text(256), 'Icon for push notification. Available only for Android and Web Platform.', true) - ->param('sound', '', new Text(256), 'Sound for push notification. Available only for Android and IOS Platform.', true) + ->param('sound', '', new Text(256), 'Sound for push notification. Available only for Android and iOS Platform.', true) ->param('color', '', new Text(256), 'Color for push notification. Available only for Android Platform.', true) ->param('tag', '', new Text(256), 'Tag for push notification. Available only for Android Platform.', true) - ->param('badge', '', new Text(256), 'Badge for push notification. Available only for IOS Platform.', true) + ->param('badge', -1, new Integer(), 'Badge for push notification. Available only for iOS Platform.', true) ->param('draft', false, new Boolean(), 'Is message a draft', true) ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), '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.', true) + ->param('contentAvailable', false, new Boolean(), 'If set to true, the notification will be delivered in the background. Available only for iOS Platform.', true) + ->param('critical', false, new Boolean(), '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.', true) + ->param('priority', 'high', new WhiteList(['normal', 'high']), 'Set the notification priority. "normal" will consider device state and may not deliver notifications immediately. "high" will always attempt to immediately deliver the notification.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, string $badge, bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, string $title, string $body, array $topics, array $users, array $targets, ?array $data, string $action, string $image, string $icon, string $sound, string $color, string $tag, int $badge, bool $draft, ?string $scheduledAt, bool $contentAvailable, bool $critical, string $priority, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $messageId = $messageId == 'unique()' ? ID::unique() : $messageId; @@ -3010,12 +3216,44 @@ App::post('/v1/messaging/messages/push') $pushData = []; - $keys = ['title', 'body', 'data', 'action', 'image', 'icon', 'sound', 'color', 'tag', 'badge']; - - foreach ($keys as $key) { - if (!empty($$key)) { - $pushData[$key] = $$key; - } + if (!empty($title)) { + $pushData['title'] = $title; + } + if (!empty($body)) { + $pushData['body'] = $body; + } + if (!empty($data)) { + $pushData['data'] = $data; + } + if (!empty($action)) { + $pushData['action'] = $action; + } + if (!empty($image)) { + $pushData['image'] = $image; + } + if (!empty($icon)) { + $pushData['icon'] = $icon; + } + if (!empty($sound)) { + $pushData['sound'] = $sound; + } + if (!empty($color)) { + $pushData['color'] = $color; + } + if (!empty($tag)) { + $pushData['tag'] = $tag; + } + if ($badge >= 0) { + $pushData['badge'] = $badge; + } + if ($contentAvailable) { + $pushData['contentAvailable'] = true; + } + if ($critical) { + $pushData['critical'] = true; + } + if (!empty($priority)) { + $pushData['priority'] = $priority; } $message = $dbForProject->createDocument('messages', new Document([ @@ -3036,8 +3274,8 @@ App::post('/v1/messaging/messages/push') ->setMessageId($message->getId()); break; case MessageStatus::SCHEDULED: - $schedule = $dbForConsole->createDocument('schedules', new Document([ - 'region' => System::getEnv('_APP_REGION', 'default'), + $schedule = $dbForPlatform->createDocument('schedules', new Document([ + 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), 'resourceInternalId' => $message->getInternalId(), @@ -3072,13 +3310,18 @@ App::get('/v1/messaging/messages') ->groups(['api', 'messaging']) ->label('scope', 'messages.read') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listMessages') - ->label('sdk.description', '/docs/references/messaging/list-messages.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listMessages', + description: '/docs/references/messaging/list-messages.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MESSAGE_LIST, + ) + ], + )) ->param('queries', [], new Messages(), '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(', ', Messages::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('dbForProject') @@ -3129,13 +3372,18 @@ App::get('/v1/messaging/messages/:messageId/logs') ->groups(['api', 'messaging']) ->label('scope', 'messages.read') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listMessageLogs') - ->label('sdk.description', '/docs/references/messaging/list-message-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listMessageLogs', + description: '/docs/references/messaging/list-message-logs.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ], + )) ->param('messageId', '', new UID(), 'Message ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), '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', true) ->inject('response') @@ -3155,13 +3403,15 @@ App::get('/v1/messaging/messages/:messageId/logs') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $grouped = Query::groupByType($queries); - $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; - $offset = $grouped['offset'] ?? 0; + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); $audit = new Audit($dbForProject); $resource = 'message/' . $messageId; - $logs = $audit->getLogsByResource($resource, $limit, $offset); + $logs = $audit->getLogsByResource($resource, $queries); $output = []; @@ -3209,7 +3459,7 @@ App::get('/v1/messaging/messages/:messageId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource), + 'total' => $audit->countLogsByResource($resource, $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -3219,13 +3469,18 @@ App::get('/v1/messaging/messages/:messageId/targets') ->groups(['api', 'messaging']) ->label('scope', 'messages.read') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'listTargets') - ->label('sdk.description', '/docs/references/messaging/list-message-targets.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET_LIST) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'listTargets', + description: '/docs/references/messaging/list-message-targets.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TARGET_LIST, + ) + ], + )) ->param('messageId', '', new UID(), 'Message 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(', ', Targets::ALLOWED_ATTRIBUTES), true) ->inject('response') @@ -3290,13 +3545,18 @@ App::get('/v1/messaging/messages/:messageId') ->groups(['api', 'messaging']) ->label('scope', 'messages.read') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'getMessage') - ->label('sdk.description', '/docs/references/messaging/get-message.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'getMessage', + description: '/docs/references/messaging/get-message.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new UID(), 'Message ID.') ->inject('dbForProject') ->inject('response') @@ -3318,13 +3578,18 @@ App::patch('/v1/messaging/messages/email/:messageId') ->label('event', 'messages.[messageId].update') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateEmail') - ->label('sdk.description', '/docs/references/messaging/update-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateEmail', + description: '/docs/references/messaging/update-email.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new UID(), 'Message ID.') ->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true) ->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true) @@ -3339,11 +3604,11 @@ App::patch('/v1/messaging/messages/email/:messageId') ->param('attachments', null, new ArrayList(new CompoundUID()), '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>.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $subject, ?string $content, ?bool $draft, ?bool $html, ?array $cc, ?array $bcc, ?string $scheduledAt, ?array $attachments, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $subject, ?string $content, ?bool $draft, ?bool $html, ?array $cc, ?array $bcc, ?string $scheduledAt, ?array $attachments, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3395,8 +3660,8 @@ App::patch('/v1/messaging/messages/email/:messageId') } if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) { - $schedule = $dbForConsole->createDocument('schedules', new Document([ - 'region' => System::getEnv('_APP_REGION', 'default'), + $schedule = $dbForPlatform->createDocument('schedules', new Document([ + 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), 'resourceInternalId' => $message->getInternalId(), @@ -3410,7 +3675,7 @@ App::patch('/v1/messaging/messages/email/:messageId') } if (!\is_null($currentScheduledAt)) { - $schedule = $dbForConsole->getDocument('schedules', $message->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $message->getAttribute('scheduleId')); $scheduledStatus = ($status ?? $message->getAttribute('status')) === MessageStatus::SCHEDULED; if ($schedule->isEmpty()) { @@ -3425,7 +3690,7 @@ App::patch('/v1/messaging/messages/email/:messageId') $schedule->setAttribute('schedule', $scheduledAt); } - $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule); + $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); } if (!\is_null($scheduledAt)) { @@ -3519,13 +3784,18 @@ App::patch('/v1/messaging/messages/sms/:messageId') ->label('event', 'messages.[messageId].update') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updateSms') - ->label('sdk.description', '/docs/references/messaging/update-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updateSms', + description: '/docs/references/messaging/update-sms.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new UID(), 'Message ID.') ->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true) ->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true) @@ -3535,11 +3805,11 @@ App::patch('/v1/messaging/messages/sms/:messageId') ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), '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.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $content, ?bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $content, ?bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3591,8 +3861,8 @@ App::patch('/v1/messaging/messages/sms/:messageId') } if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) { - $schedule = $dbForConsole->createDocument('schedules', new Document([ - 'region' => System::getEnv('_APP_REGION', 'default'), + $schedule = $dbForPlatform->createDocument('schedules', new Document([ + 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), 'resourceInternalId' => $message->getInternalId(), @@ -3606,7 +3876,7 @@ App::patch('/v1/messaging/messages/sms/:messageId') } if (!\is_null($currentScheduledAt)) { - $schedule = $dbForConsole->getDocument('schedules', $message->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $message->getAttribute('scheduleId')); $scheduledStatus = ($status ?? $message->getAttribute('status')) === MessageStatus::SCHEDULED; if ($schedule->isEmpty()) { @@ -3621,7 +3891,7 @@ App::patch('/v1/messaging/messages/sms/:messageId') $schedule->setAttribute('schedule', $scheduledAt); } - $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule); + $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); } if (!\is_null($scheduledAt)) { @@ -3675,13 +3945,18 @@ App::patch('/v1/messaging/messages/push/:messageId') ->label('event', 'messages.[messageId].update') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'updatePush') - ->label('sdk.description', '/docs/references/messaging/update-push.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MESSAGE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'updatePush', + description: '/docs/references/messaging/update-push.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MESSAGE, + ) + ] + )) ->param('messageId', '', new UID(), 'Message ID.') ->param('topics', null, new ArrayList(new UID()), 'List of Topic IDs.', true) ->param('users', null, new ArrayList(new UID()), 'List of User IDs.', true) @@ -3698,13 +3973,16 @@ App::patch('/v1/messaging/messages/push/:messageId') ->param('badge', null, new Integer(), 'Badge for push notification. Available only for iOS platforms.', true) ->param('draft', null, new Boolean(), 'Is message a draft', true) ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true), '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.', true) + ->param('contentAvailable', null, new Boolean(), 'If set to true, the notification will be delivered in the background. Available only for iOS Platform.', true) + ->param('critical', null, new Boolean(), '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.', true) + ->param('priority', null, new WhiteList(['normal', 'high']), 'Set the notification priority. "normal" will consider device battery state and may send notifications later. "high" will always attempt to immediately deliver the notification.', true) ->inject('queueForEvents') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('project') ->inject('queueForMessaging') ->inject('response') - ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $title, ?string $body, ?array $data, ?string $action, ?string $image, ?string $icon, ?string $sound, ?string $color, ?string $tag, ?int $badge, ?bool $draft, ?string $scheduledAt, Event $queueForEvents, Database $dbForProject, Database $dbForConsole, Document $project, Messaging $queueForMessaging, Response $response) { + ->action(function (string $messageId, ?array $topics, ?array $users, ?array $targets, ?string $title, ?string $body, ?array $data, ?string $action, ?string $image, ?string $icon, ?string $sound, ?string $color, ?string $tag, ?int $badge, ?bool $draft, ?string $scheduledAt, ?bool $contentAvailable, ?bool $critical, ?string $priority, Event $queueForEvents, Database $dbForProject, Database $dbForPlatform, Document $project, Messaging $queueForMessaging, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3756,8 +4034,8 @@ App::patch('/v1/messaging/messages/push/:messageId') } if (\is_null($currentScheduledAt) && !\is_null($scheduledAt)) { - $schedule = $dbForConsole->createDocument('schedules', new Document([ - 'region' => System::getEnv('_APP_REGION', 'default'), + $schedule = $dbForPlatform->createDocument('schedules', new Document([ + 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), 'resourceInternalId' => $message->getInternalId(), @@ -3771,7 +4049,7 @@ App::patch('/v1/messaging/messages/push/:messageId') } if (!\is_null($currentScheduledAt)) { - $schedule = $dbForConsole->getDocument('schedules', $message->getAttribute('scheduleId')); + $schedule = $dbForPlatform->getDocument('schedules', $message->getAttribute('scheduleId')); $scheduledStatus = ($status ?? $message->getAttribute('status')) === MessageStatus::SCHEDULED; if ($schedule->isEmpty()) { @@ -3786,7 +4064,7 @@ App::patch('/v1/messaging/messages/push/:messageId') $schedule->setAttribute('schedule', $scheduledAt); } - $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule); + $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule); } if (!\is_null($scheduledAt)) { @@ -3843,6 +4121,18 @@ App::patch('/v1/messaging/messages/push/:messageId') $pushData['badge'] = $badge; } + if (!\is_null($contentAvailable)) { + $pushData['contentAvailable'] = $contentAvailable; + } + + if (!\is_null($critical)) { + $pushData['critical'] = $critical; + } + + if (!\is_null($priority)) { + $pushData['priority'] = $priority; + } + if (!\is_null($image)) { [$bucketId, $fileId] = CompoundUID::parse($image); @@ -3914,19 +4204,25 @@ App::delete('/v1/messaging/messages/:messageId') ->label('event', 'messages.[messageId].delete') ->label('scope', 'messages.write') ->label('resourceType', RESOURCE_TYPE_MESSAGES) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN, APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'messaging') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/messaging/delete-message.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'messaging', + name: 'delete', + description: '/docs/references/messaging/delete-message.md', + auth: [AuthType::ADMIN, AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('messageId', '', new UID(), 'Message ID.') ->inject('dbForProject') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForEvents') ->inject('response') - ->action(function (string $messageId, Database $dbForProject, Database $dbForConsole, Event $queueForEvents, Response $response) { + ->action(function (string $messageId, Database $dbForProject, Database $dbForPlatform, Event $queueForEvents, Response $response) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3949,7 +4245,7 @@ App::delete('/v1/messaging/messages/:messageId') if (!empty($scheduleId)) { try { - $dbForConsole->deleteDocument('schedules', $scheduleId); + $dbForPlatform->deleteDocument('schedules', $scheduleId); } catch (Exception) { // Ignore } diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index bebb6ebaea..4a1e5de227 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -1,30 +1,35 @@ <?php -use Appwrite\Auth\OAuth2\Firebase as OAuth2Firebase; +use Appwrite\Auth\Auth; use Appwrite\Event\Event; use Appwrite\Event\Migration; use Appwrite\Extend\Exception; -use Appwrite\Permission; -use Appwrite\Role; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Database\Validator\CompoundUID; use Appwrite\Utopia\Database\Validator\Queries\Migrations; -use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; use Utopia\Database\Validator\UID; +use Utopia\Migration\Resource; use Utopia\Migration\Sources\Appwrite; +use Utopia\Migration\Sources\CSV; use Utopia\Migration\Sources\Firebase; use Utopia\Migration\Sources\NHost; use Utopia\Migration\Sources\Supabase; -use Utopia\System\System; +use Utopia\Migration\Transfer; +use Utopia\Storage\Compression\Compression; +use Utopia\Storage\Device; use Utopia\Validator\ArrayList; -use Utopia\Validator\Host; use Utopia\Validator\Integer; use Utopia\Validator\Text; use Utopia\Validator\URL; @@ -38,17 +43,22 @@ App::post('/v1/migrations/appwrite') ->label('scope', 'migrations.write') ->label('event', 'migrations.[migrationId].create') ->label('audits.event', 'migration.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createAppwriteMigration') - ->label('sdk.description', '/docs/references/migrations/migration-appwrite.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'createAppwriteMigration', + description: '/docs/references/migrations/migration-appwrite.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Appwrite::getSupportedResources())), 'List of resources to migrate') - ->param('endpoint', '', new URL(), "Source's Appwrite Endpoint") - ->param('projectId', '', new UID(), "Source's Project ID") - ->param('apiKey', '', new Text(512), "Source's API Key") + ->param('endpoint', '', new URL(), 'Source Appwrite endpoint') + ->param('projectId', '', new UID(), 'Source Project ID') + ->param('apiKey', '', new Text(512), 'Source API Key') ->inject('response') ->inject('dbForProject') ->inject('project') @@ -87,122 +97,24 @@ App::post('/v1/migrations/appwrite') ->dynamic($migration, Response::MODEL_MIGRATION); }); -App::post('/v1/migrations/firebase/oauth') - ->groups(['api', 'migrations']) - ->desc('Migrate Firebase data (OAuth)') - ->label('scope', 'migrations.write') - ->label('event', 'migrations.[migrationId].create') - ->label('audits.event', 'migration.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createFirebaseOAuthMigration') - ->label('sdk.description', '/docs/references/migrations/migration-firebase.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) - ->param('resources', [], new ArrayList(new WhiteList(Firebase::getSupportedResources())), 'List of resources to migrate') - ->param('projectId', '', new Text(65536), 'Project ID of the Firebase Project') - ->inject('response') - ->inject('dbForProject') - ->inject('dbForConsole') - ->inject('project') - ->inject('user') - ->inject('queueForEvents') - ->inject('queueForMigrations') - ->inject('request') - ->action(function (array $resources, string $projectId, Response $response, Database $dbForProject, Database $dbForConsole, Document $project, Document $user, Event $queueForEvents, Migration $queueForMigrations, Request $request) { - $firebase = new OAuth2Firebase( - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' - ); - - $identity = $dbForConsole->findOne('identities', [ - Query::equal('provider', ['firebase']), - Query::equal('userInternalId', [$user->getInternalId()]), - ]); - if ($identity->isEmpty()) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $accessToken = $identity->getAttribute('providerAccessToken'); - $refreshToken = $identity->getAttribute('providerRefreshToken'); - $accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry'); - - $isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now'); - if ($isExpired) { - $firebase->refreshTokens($refreshToken); - - $accessToken = $firebase->getAccessToken(''); - $refreshToken = $firebase->getRefreshToken(''); - - $verificationId = $firebase->getUserID($accessToken); - - if (empty($verificationId)) { - throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, 'Another request is currently refreshing OAuth token. Please try again.'); - } - - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); - - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); - } - - if ($identity->getAttribute('secrets')) { - $serviceAccount = $identity->getAttribute('secrets'); - } else { - $firebase->cleanupServiceAccounts($accessToken, $projectId); - $serviceAccount = $firebase->createServiceAccount($accessToken, $projectId); - $identity = $identity - ->setAttribute('secrets', json_encode($serviceAccount)); - - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); - } - - $migration = $dbForProject->createDocument('migrations', new Document([ - '$id' => ID::unique(), - 'status' => 'pending', - 'stage' => 'init', - 'source' => Firebase::getName(), - 'destination' => Appwrite::getName(), - 'credentials' => [ - 'serviceAccount' => json_encode($serviceAccount), - ], - 'resources' => $resources, - 'statusCounters' => '{}', - 'resourceData' => '{}', - 'errors' => [] - ])); - - $queueForEvents->setParam('migrationId', $migration->getId()); - - // Trigger Transfer - $queueForMigrations - ->setMigration($migration) - ->setProject($project) - ->setUser($user) - ->trigger(); - - $response - ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($migration, Response::MODEL_MIGRATION); - }); - App::post('/v1/migrations/firebase') ->groups(['api', 'migrations']) - ->desc('Migrate Firebase data (Service Account)') + ->desc('Migrate Firebase data') ->label('scope', 'migrations.write') ->label('event', 'migrations.[migrationId].create') ->label('audits.event', 'migration.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createFirebaseMigration') - ->label('sdk.description', '/docs/references/migrations/migration-firebase.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'createFirebaseMigration', + description: '/docs/references/migrations/migration-firebase.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Firebase::getSupportedResources())), 'List of resources to migrate') ->param('serviceAccount', '', new Text(65536), 'JSON of the Firebase service account credentials') ->inject('response') @@ -257,13 +169,18 @@ App::post('/v1/migrations/supabase') ->label('scope', 'migrations.write') ->label('event', 'migrations.[migrationId].create') ->label('audits.event', 'migration.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createSupabaseMigration') - ->label('sdk.description', '/docs/references/migrations/migration-supabase.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'createSupabaseMigration', + description: '/docs/references/migrations/migration-supabase.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Supabase::getSupportedResources(), true)), 'List of resources to migrate') ->param('endpoint', '', new URL(), 'Source\'s Supabase Endpoint') ->param('apiKey', '', new Text(512), 'Source\'s API Key') @@ -318,13 +235,18 @@ App::post('/v1/migrations/nhost') ->label('scope', 'migrations.write') ->label('event', 'migrations.[migrationId].create') ->label('audits.event', 'migration.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createNHostMigration') - ->label('sdk.description', '/docs/references/migrations/migration-nhost.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'createNHostMigration', + description: '/docs/references/migrations/migration-nhost.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(NHost::getSupportedResources())), 'List of resources to migrate') ->param('subdomain', '', new Text(512), 'Source\'s Subdomain') ->param('region', '', new Text(512), 'Source\'s Region') @@ -375,17 +297,114 @@ App::post('/v1/migrations/nhost') ->dynamic($migration, Response::MODEL_MIGRATION); }); +App::post('/v1/migrations/csv') + ->groups(['api', 'migrations']) + ->desc('Import documents from a CSV') + ->label('scope', 'migrations.write') + ->label('event', 'migrations.[migrationId].create') + ->label('audits.event', 'migration.create') + ->label('sdk', new Method( + namespace: 'migrations', + name: 'createCsvMigration', + description: '/docs/references/migrations/migration-csv.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) + ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') + ->param('fileId', '', new UID(), 'File ID.') + ->param('resourceId', null, new CompoundUID(), 'Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.') + ->inject('response') + ->inject('dbForProject') + ->inject('project') + ->inject('deviceForFiles') + ->inject('deviceForImports') + ->inject('queueForEvents') + ->inject('queueForMigrations') + ->action(function (string $bucketId, string $fileId, string $resourceId, Response $response, Database $dbForProject, Document $project, Device $deviceForFiles, Device $deviceForImports, Event $queueForEvents, Migration $queueForMigrations) { + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + + if ($bucket->isEmpty() || (!$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); + } + + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + if ($file->isEmpty()) { + throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); + } + + $path = $file->getAttribute('path', ''); + if (!$deviceForFiles->exists($path)) { + throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); + } + + if (!empty($file->getAttribute('openSSLCipher')) || $file->getAttribute('algorithm', Compression::NONE) !== Compression::NONE) { + throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED, "Only uncompressed, unencrypted CSV files can be used for document import."); + } + + // copy to temporary folder + $migrationId = ID::unique(); + $newPath = $deviceForImports->getPath('/' . $migrationId . '_' . $fileId . '.csv'); + if (!$deviceForFiles->transfer($path, $newPath, $deviceForImports)) { + throw new \Exception("Unable to copy file"); + } + + $fileSize = $deviceForImports->getFileSize($path); + $resources = Transfer::extractServices([Transfer::GROUP_DATABASES]); + + $migration = $dbForProject->createDocument('migrations', new Document([ + '$id' => $migrationId, + 'status' => 'pending', + 'stage' => 'init', + 'source' => CSV::getName(), + 'destination' => Appwrite::getName(), + 'resources' => $resources, + 'resourceId' => $resourceId, + 'resourceType' => Resource::TYPE_DATABASE, + 'statusCounters' => [], + 'resourceData' => [], + 'errors' => [], + 'options' => [ + 'path' => $newPath, + 'size' => $fileSize, + ], + ])); + + $queueForEvents->setParam('migrationId', $migration->getId()); + + $queueForMigrations + ->setMigration($migration) + ->setProject($project) + ->trigger(); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($migration, Response::MODEL_MIGRATION); + }); + App::get('/v1/migrations') ->groups(['api', 'migrations']) ->desc('List migrations') ->label('scope', 'migrations.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'list') - ->label('sdk.description', '/docs/references/migrations/list-migrations.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_LIST) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'list', + description: '/docs/references/migrations/list-migrations.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION_LIST, + ) + ] + )) ->param('queries', [], new Migrations(), '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 ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Migrations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -438,13 +457,18 @@ App::get('/v1/migrations/:migrationId') ->groups(['api', 'migrations']) ->desc('Get migration') ->label('scope', 'migrations.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/migrations/get-migration.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'get', + description: '/docs/references/migrations/get-migration.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('migrationId', '', new UID(), 'Migration unique ID.') ->inject('response') ->inject('dbForProject') @@ -462,13 +486,18 @@ App::get('/v1/migrations/appwrite/report') ->groups(['api', 'migrations']) ->desc('Generate a report on Appwrite data') ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'getAppwriteReport') - ->label('sdk.description', '/docs/references/migrations/migration-appwrite-report.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_REPORT) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'getAppwriteReport', + description: '/docs/references/migrations/migration-appwrite-report.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION_REPORT, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Appwrite::getSupportedResources())), 'List of resources to migrate') ->param('endpoint', '', new URL(), "Source's Appwrite Endpoint") ->param('projectID', '', new Text(512), "Source's Project ID") @@ -504,13 +533,18 @@ App::get('/v1/migrations/firebase/report') ->groups(['api', 'migrations']) ->desc('Generate a report on Firebase data') ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'getFirebaseReport') - ->label('sdk.description', '/docs/references/migrations/migration-firebase-report.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_REPORT) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'getFirebaseReport', + description: '/docs/references/migrations/migration-firebase-report.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION_REPORT, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Firebase::getSupportedResources())), 'List of resources to migrate') ->param('serviceAccount', '', new Text(65536), 'JSON of the Firebase service account credentials') ->inject('response') @@ -547,379 +581,22 @@ App::get('/v1/migrations/firebase/report') ->dynamic(new Document($report), Response::MODEL_MIGRATION_REPORT); }); -App::get('/v1/migrations/firebase/report/oauth') - ->groups(['api', 'migrations']) - ->desc('Generate a report on Firebase data using OAuth') - ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'getFirebaseReportOAuth') - ->label('sdk.description', '/docs/references/migrations/migration-firebase-report.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_REPORT) - ->param('resources', [], new ArrayList(new WhiteList(Firebase::getSupportedResources())), 'List of resources to migrate') - ->param('projectId', '', new Text(65536), 'Project ID') - ->inject('response') - ->inject('request') - ->inject('user') - ->inject('dbForConsole') - ->action(function (array $resources, string $projectId, Response $response, Request $request, Document $user, Database $dbForConsole) { - $firebase = new OAuth2Firebase( - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' - ); - - $identity = $dbForConsole->findOne('identities', [ - Query::equal('provider', ['firebase']), - Query::equal('userInternalId', [$user->getInternalId()]), - ]); - - if ($identity->isEmpty()) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $accessToken = $identity->getAttribute('providerAccessToken'); - $refreshToken = $identity->getAttribute('providerRefreshToken'); - $accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry'); - - if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - if (System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', '') === '' || System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', '') === '') { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now'); - if ($isExpired) { - $firebase->refreshTokens($refreshToken); - - $accessToken = $firebase->getAccessToken(''); - $refreshToken = $firebase->getRefreshToken(''); - - $verificationId = $firebase->getUserID($accessToken); - - if (empty($verificationId)) { - throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, 'Another request is currently refreshing OAuth token. Please try again.'); - } - - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); - - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); - } - - // Get Service Account - if ($identity->getAttribute('secrets')) { - $serviceAccount = $identity->getAttribute('secrets'); - } else { - $firebase->cleanupServiceAccounts($accessToken, $projectId); - $serviceAccount = $firebase->createServiceAccount($accessToken, $projectId); - $identity = $identity - ->setAttribute('secrets', json_encode($serviceAccount)); - - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); - } - - $firebase = new Firebase($serviceAccount); - - try { - $report = $firebase->report($resources); - } catch (\Throwable $e) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Source Error: ' . $e->getMessage()); - } - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic(new Document($report), Response::MODEL_MIGRATION_REPORT); - }); - -App::get('/v1/migrations/firebase/connect') - ->desc('Authorize with Firebase') - ->groups(['api', 'migrations']) - ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'createFirebaseAuth') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY) - ->label('sdk.response.type', Response::CONTENT_TYPE_HTML) - ->label('sdk.methodType', 'webAuth') - ->label('sdk.hide', true) - ->param('redirect', '', fn ($clients) => new Host($clients), 'URL to redirect back to your Firebase authorization. Only console hostnames are allowed.', true, ['clients']) - ->param('projectId', '', new UID(), 'Project ID') - ->inject('response') - ->inject('request') - ->inject('user') - ->inject('dbForConsole') - ->action(function (string $redirect, string $projectId, Response $response, Request $request, Document $user, Database $dbForConsole) { - $state = \json_encode([ - 'projectId' => $projectId, - 'redirect' => $redirect, - ]); - - $prefs = $user->getAttribute('prefs', []); - $prefs['migrationState'] = $state; - $user->setAttribute('prefs', $prefs); - $dbForConsole->updateDocument('users', $user->getId(), $user); - - $oauth2 = new OAuth2Firebase( - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' - ); - $url = $oauth2->getLoginURL(); - - $response - ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') - ->addHeader('Pragma', 'no-cache') - ->redirect($url); - }); - -App::get('/v1/migrations/firebase/redirect') - ->desc('Capture and receive data on Firebase authorization') - ->groups(['api', 'migrations']) - ->label('scope', 'public') - ->label('error', __DIR__ . '/../../views/general/error.phtml') - ->param('code', '', new Text(2048), 'OAuth2 code. This is a temporary code that the will be later exchanged for an access token.', true) - ->inject('user') - ->inject('project') - ->inject('request') - ->inject('response') - ->inject('dbForConsole') - ->action(function (string $code, Document $user, Document $project, Request $request, Response $response, Database $dbForConsole) { - $state = $user['prefs']['migrationState'] ?? '{}'; - $prefs['migrationState'] = ''; - $user->setAttribute('prefs', $prefs); - $dbForConsole->updateDocument('users', $user->getId(), $user); - - if (empty($state)) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Installation requests from organisation members for the Appwrite Google App are currently unsupported.'); - } - - $state = \json_decode($state, true); - $redirect = $state['redirect'] ?? ''; - $projectId = $state['projectId'] ?? ''; - - $project = $dbForConsole->getDocument('projects', $projectId); - - if (empty($redirect)) { - $redirect = $request->getProtocol() . '://' . $request->getHostname() . '/console/project-$projectId/settings/migrations'; - } - - if ($project->isEmpty()) { - $response - ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') - ->addHeader('Pragma', 'no-cache') - ->redirect($redirect); - - return; - } - - // OAuth Authroization - if (!empty($code)) { - $oauth2 = new OAuth2Firebase( - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' - ); - - $accessToken = $oauth2->getAccessToken($code); - $refreshToken = $oauth2->getRefreshToken($code); - $accessTokenExpiry = $oauth2->getAccessTokenExpiry($code); - $email = $oauth2->getUserEmail($accessToken); - $oauth2ID = $oauth2->getUserID($accessToken); - - if (empty($accessToken)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to get access token.'); - } - - if (empty($refreshToken)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to get refresh token.'); - } - - if (empty($accessTokenExpiry)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to get access token expiry.'); - } - - // Makes sure this email is not already used in another identity - $identity = $dbForConsole->findOne('identities', [ - Query::equal('providerEmail', [$email]), - ]); - - if (!$identity->isEmpty()) { - if ($identity->getAttribute('userInternalId', '') !== $user->getInternalId()) { - throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); - } - } - - if (!$identity->isEmpty()) { - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry)); - - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); - } else { - $identity = $dbForConsole->createDocument('identities', new Document([ - '$id' => ID::unique(), - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'userInternalId' => $user->getInternalId(), - 'userId' => $user->getId(), - 'provider' => 'firebase', - 'providerUid' => $oauth2ID, - 'providerEmail' => $email, - 'providerAccessToken' => $accessToken, - 'providerRefreshToken' => $refreshToken, - 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry), - ])); - } - } else { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Missing OAuth2 code.'); - } - - $response - ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') - ->addHeader('Pragma', 'no-cache') - ->redirect($redirect); - }); - -App::get('/v1/migrations/firebase/projects') - ->desc('List Firebase projects') - ->groups(['api', 'migrations']) - ->label('scope', 'migrations.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'listFirebaseProjects') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_FIREBASE_PROJECT_LIST) - ->inject('user') - ->inject('response') - ->inject('project') - ->inject('dbForConsole') - ->inject('request') - ->action(function (Document $user, Response $response, Document $project, Database $dbForConsole, Request $request) { - $firebase = new OAuth2Firebase( - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''), - System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''), - $request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect' - ); - - $identity = $dbForConsole->findOne('identities', [ - Query::equal('provider', ['firebase']), - Query::equal('userInternalId', [$user->getInternalId()]), - ]); - - if ($identity->isEmpty()) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $accessToken = $identity->getAttribute('providerAccessToken'); - $refreshToken = $identity->getAttribute('providerRefreshToken'); - $accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry'); - - if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - if (System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', '') === '' || System::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', '') === '') { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - try { - $isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now'); - if ($isExpired) { - try { - $firebase->refreshTokens($refreshToken); - } catch (\Throwable $e) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $accessToken = $firebase->getAccessToken(''); - $refreshToken = $firebase->getRefreshToken(''); - - $verificationId = $firebase->getUserID($accessToken); - - if (empty($verificationId)) { - throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, 'Another request is currently refreshing OAuth token. Please try again.'); - } - - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry(''))); - - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); - } - - $projects = $firebase->getProjects($accessToken); - - $output = []; - foreach ($projects as $project) { - $output[] = [ - 'displayName' => $project['displayName'], - 'projectId' => $project['projectId'], - ]; - } - } catch (\Throwable $e) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } - - $response->dynamic(new Document([ - 'projects' => $output, - 'total' => count($output), - ]), Response::MODEL_MIGRATION_FIREBASE_PROJECT_LIST); - }); - -App::get('/v1/migrations/firebase/deauthorize') - ->desc('Revoke Appwrite\'s authorization to access Firebase projects') - ->groups(['api', 'migrations']) - ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'deleteFirebaseAuth') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->inject('user') - ->inject('response') - ->inject('dbForConsole') - ->action(function (Document $user, Response $response, Database $dbForConsole) { - $identity = $dbForConsole->findOne('identities', [ - Query::equal('provider', ['firebase']), - Query::equal('userInternalId', [$user->getInternalId()]), - ]); - - if ($identity->isEmpty()) { - throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Not authenticated with Firebase'); //TODO: Replace with USER_IDENTITY_NOT_FOUND - } - - $dbForConsole->deleteDocument('identities', $identity->getId()); - - $response->noContent(); - }); - App::get('/v1/migrations/supabase/report') ->groups(['api', 'migrations']) ->desc('Generate a report on Supabase Data') ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'getSupabaseReport') - ->label('sdk.description', '/docs/references/migrations/migration-supabase-report.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_REPORT) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'getSupabaseReport', + description: '/docs/references/migrations/migration-supabase-report.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION_REPORT, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(Supabase::getSupportedResources(), true)), 'List of resources to migrate') ->param('endpoint', '', new URL(), 'Source\'s Supabase Endpoint.') ->param('apiKey', '', new Text(512), 'Source\'s API Key.') @@ -956,13 +633,18 @@ App::get('/v1/migrations/nhost/report') ->groups(['api', 'migrations']) ->desc('Generate a report on NHost Data') ->label('scope', 'migrations.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'getNHostReport') - ->label('sdk.description', '/docs/references/migrations/migration-nhost-report.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION_REPORT) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'getNHostReport', + description: '/docs/references/migrations/migration-nhost-report.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MIGRATION_REPORT, + ) + ] + )) ->param('resources', [], new ArrayList(new WhiteList(NHost::getSupportedResources())), 'List of resources to migrate.') ->param('subdomain', '', new Text(512), 'Source\'s Subdomain.') ->param('region', '', new Text(512), 'Source\'s Region.') @@ -1002,13 +684,18 @@ App::patch('/v1/migrations/:migrationId') ->label('event', 'migrations.[migrationId].retry') ->label('audits.event', 'migration.retry') ->label('audits.resource', 'migrations/{request.migrationId}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'retry') - ->label('sdk.description', '/docs/references/migrations/retry-migration.md') - ->label('sdk.response.code', Response::STATUS_CODE_ACCEPTED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MIGRATION) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'retry', + description: '/docs/references/migrations/retry-migration.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_MIGRATION, + ) + ] + )) ->param('migrationId', '', new UID(), 'Migration unique ID.') ->inject('response') ->inject('dbForProject') @@ -1047,12 +734,19 @@ App::delete('/v1/migrations/:migrationId') ->label('event', 'migrations.[migrationId].delete') ->label('audits.event', 'migrationId.delete') ->label('audits.resource', 'migrations/{request.migrationId}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'migrations') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/migrations/delete-migration.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'migrations', + name: 'delete', + description: '/docs/references/migrations/delete-migration.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('migrationId', '', new UID(), 'Migration ID.') ->inject('response') ->inject('dbForProject') diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 7ac49466a2..4c7b21c0f8 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -1,6 +1,10 @@ <?php use Appwrite\Extend\Exception; +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\Database\Database; @@ -21,23 +25,34 @@ App::get('/v1/project/usage') ->desc('Get project usage stats') ->groups(['api', 'usage']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_PROJECT) + ->label('sdk', new Method( + namespace: 'project', + name: 'getUsage', + description: '/docs/references/project/get-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_PROJECT, + ) + ] + )) ->param('startDate', '', new DateTimeValidator(), 'Starting date for the usage') ->param('endDate', '', new DateTimeValidator(), 'End date for the usage') ->param('period', '1d', new WhiteList(['1h', '1d']), 'Period used', true) ->inject('response') + ->inject('project') ->inject('dbForProject') - ->action(function (string $startDate, string $endDate, string $period, Response $response, Database $dbForProject) { + ->inject('getLogsDB') + ->inject('smsRates') + ->action(function (string $startDate, string $endDate, string $period, Response $response, Document $project, Database $dbForProject, callable $getLogsDB, array $smsRates) { $stats = $total = $usage = []; $format = 'Y-m-d 00:00:00'; $firstDay = (new DateTime($startDate))->format($format); $lastDay = (new DateTime($endDate))->format($format); + $dbForLogs = call_user_func($getLogsDB, $project); + $metrics = [ 'total' => [ METRIC_EXECUTIONS, @@ -50,7 +65,10 @@ App::get('/v1/project/usage') METRIC_FILES_STORAGE, METRIC_DATABASES_STORAGE, METRIC_DEPLOYMENTS_STORAGE, - METRIC_BUILDS_STORAGE + METRIC_BUILDS_STORAGE, + METRIC_DATABASES_OPERATIONS_READS, + METRIC_DATABASES_OPERATIONS_WRITES, + METRIC_FILES_IMAGES_TRANSFORMED, ], 'period' => [ METRIC_NETWORK_REQUESTS, @@ -60,7 +78,10 @@ App::get('/v1/project/usage') METRIC_EXECUTIONS, METRIC_DATABASES_STORAGE, METRIC_EXECUTIONS_MB_SECONDS, - METRIC_BUILDS_MB_SECONDS + METRIC_BUILDS_MB_SECONDS, + METRIC_DATABASES_OPERATIONS_READS, + METRIC_DATABASES_OPERATIONS_WRITES, + METRIC_FILES_IMAGES_TRANSFORMED, ] ]; @@ -79,9 +100,11 @@ App::get('/v1/project/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - Authorization::skip(function () use ($dbForProject, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { + Authorization::skip(function () use ($dbForProject, $dbForLogs, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { foreach ($metrics['total'] as $metric) { - $result = $dbForProject->findOne('stats', [ + $db = ($metric === METRIC_FILES_IMAGES_TRANSFORMED) ? $dbForLogs : $dbForProject; + + $result = $db->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -89,7 +112,9 @@ App::get('/v1/project/usage') } foreach ($metrics['period'] as $metric) { - $results = $dbForProject->find('stats', [ + $db = ($metric === METRIC_FILES_IMAGES_TRANSFORMED) ? $dbForLogs : $dbForProject; + + $results = $db->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::greaterThanEqual('time', $firstDay), @@ -124,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(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -140,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(['{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']) @@ -156,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(['{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']) @@ -205,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}'], [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(['{functionInternalId}'], [$function->getInternalId()], METRIC_FUNCTION_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']) @@ -229,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(['{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']) @@ -245,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(['{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']) @@ -258,6 +283,46 @@ App::get('/v1/project/usage') ]; }, $dbForProject->find('functions')); + // This total is includes free and paid SMS usage + $authPhoneTotal = Authorization::skip(fn () => $dbForProject->sum('stats', 'value', [ + Query::equal('metric', [METRIC_AUTH_METHOD_PHONE]), + Query::equal('period', ['1d']), + Query::greaterThanEqual('time', $firstDay), + Query::lessThan('time', $lastDay), + ])); + + // This estimate is only for paid SMS usage + $authPhoneMetrics = Authorization::skip(fn () => $dbForProject->find('stats', [ + Query::startsWith('metric', METRIC_AUTH_METHOD_PHONE . '.'), + Query::equal('period', ['1d']), + Query::greaterThanEqual('time', $firstDay), + Query::lessThan('time', $lastDay), + ])); + + $authPhoneEstimate = 0.0; + $authPhoneCountryBreakdown = []; + foreach ($authPhoneMetrics as $metric) { + $parts = explode('.', $metric->getAttribute('metric')); + $countryCode = $parts[3] ?? null; + if ($countryCode === null) { + continue; + } + + $value = $metric->getAttribute('value', 0); + + if (isset($smsRates[$countryCode])) { + $authPhoneEstimate += $value * $smsRates[$countryCode]; + } + + $authPhoneCountryBreakdown[] = [ + 'name' => $countryCode, + 'value' => $value, + 'estimate' => isset($smsRates[$countryCode]) + ? $value * $smsRates[$countryCode] + : 0.0, + ]; + } + // merge network inbound + outbound $projectBandwidth = []; foreach ($usage[METRIC_NETWORK_INBOUND] as $item) { @@ -296,14 +361,21 @@ App::get('/v1/project/usage') 'functionsStorageTotal' => $total[METRIC_DEPLOYMENTS_STORAGE] + $total[METRIC_BUILDS_STORAGE], 'buildsStorageTotal' => $total[METRIC_BUILDS_STORAGE], 'deploymentsStorageTotal' => $total[METRIC_DEPLOYMENTS_STORAGE], + 'databasesReadsTotal' => $total[METRIC_DATABASES_OPERATIONS_READS], + 'databasesWritesTotal' => $total[METRIC_DATABASES_OPERATIONS_WRITES], 'executionsBreakdown' => $executionsBreakdown, - 'executionsMbSecondsBreakdown' => $executionsMbSecondsBreakdown, - 'buildsMbSecondsBreakdown' => $buildsMbSecondsBreakdown, 'bucketsBreakdown' => $bucketsBreakdown, + 'databasesReads' => $usage[METRIC_DATABASES_OPERATIONS_READS], + 'databasesWrites' => $usage[METRIC_DATABASES_OPERATIONS_WRITES], 'databasesStorageBreakdown' => $databasesStorageBreakdown, 'executionsMbSecondsBreakdown' => $executionsMbSecondsBreakdown, 'buildsMbSecondsBreakdown' => $buildsMbSecondsBreakdown, 'functionsStorageBreakdown' => $functionsStorageBreakdown, + 'authPhoneTotal' => $authPhoneTotal, + 'authPhoneEstimate' => $authPhoneEstimate, + 'authPhoneCountryBreakdown' => $authPhoneCountryBreakdown, + 'imageTransformations' => $usage[METRIC_FILES_IMAGES_TRANSFORMED], + 'imageTransformationsTotal' => $total[METRIC_FILES_IMAGES_TRANSFORMED], ]), Response::MODEL_USAGE_PROJECT); }); @@ -314,21 +386,26 @@ App::post('/v1/project/variables') ->groups(['api']) ->label('scope', 'projects.write') ->label('audits.event', 'variable.create') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'createVariable') - ->label('sdk.description', '/docs/references/project/create-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) + ->label('sdk', new Method( + namespace: 'project', + name: 'createVariable', + description: '/docs/references/project/create-variable.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_VARIABLE, + ) + ] + )) ->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false) ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false) - ->param('secret', false, new Boolean(), 'Is secret? Secret variables can only be updated or deleted, they cannot be read.', true) + ->param('secret', true, new Boolean(), 'Secret variables can be updated or deleted, but only projects can read them during build and runtime.', true) ->inject('project') ->inject('response') ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (string $key, string $value, bool $secret, Document $project, Response $response, Database $dbForProject, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $key, string $value, bool $secret, Document $project, Response $response, Database $dbForProject, Database $dbForPlatform) { $variableId = ID::unique(); $variable = new Document([ @@ -370,13 +447,18 @@ App::get('/v1/project/variables') ->desc('List variables') ->groups(['api']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'listVariables') - ->label('sdk.description', '/docs/references/project/list-variables.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE_LIST) + ->label('sdk', new Method( + namespace: 'project', + name: 'listVariables', + description: '/docs/references/project/list-variables.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE_LIST, + ) + ] + )) ->inject('response') ->inject('dbForProject') ->action(function (Response $response, Database $dbForProject) { @@ -395,13 +477,18 @@ App::get('/v1/project/variables/:variableId') ->desc('Get variable') ->groups(['api']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'getVariable') - ->label('sdk.description', '/docs/references/project/get-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) + ->label('sdk', new Method( + namespace: 'project', + name: 'getVariable', + description: '/docs/references/project/get-variable.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE, + ) + ] + )) ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->inject('response') ->inject('project') @@ -419,29 +506,40 @@ App::put('/v1/project/variables/:variableId') ->desc('Update variable') ->groups(['api']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'updateVariable') - ->label('sdk.description', '/docs/references/project/update-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VARIABLE) + ->label('sdk', new Method( + namespace: 'project', + name: 'updateVariable', + description: '/docs/references/project/update-variable.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE, + ) + ] + )) ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false) ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true) + ->param('secret', null, new Boolean(), 'Secret variables can be updated or deleted, but only projects can read them during build and runtime.', true) ->inject('project') ->inject('response') ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (string $variableId, string $key, ?string $value, Document $project, Response $response, Database $dbForProject, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $variableId, string $key, ?string $value, ?bool $secret, Document $project, Response $response, Database $dbForProject, Database $dbForPlatform) { $variable = $dbForProject->getDocument('variables', $variableId); if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceType') !== 'project') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } + if ($variable->getAttribute('secret') === true && $secret === false) { + throw new Exception(Exception::VARIABLE_CANNOT_UNSET_SECRET); + } + $variable ->setAttribute('key', $key) ->setAttribute('value', $value ?? $variable->getAttribute('value')) + ->setAttribute('secret', $secret ?? $variable->getAttribute('secret')) ->setAttribute('search', implode(' ', [$variableId, $key, 'project'])); try { @@ -465,12 +563,19 @@ App::delete('/v1/project/variables/:variableId') ->desc('Delete variable') ->groups(['api']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'project') - ->label('sdk.method', 'deleteVariable') - ->label('sdk.description', '/docs/references/project/delete-variable.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'project', + name: 'deleteVariable', + description: '/docs/references/project/delete-variable.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('variableId', '', new UID(), 'Variable unique ID.', false) ->inject('project') ->inject('response') diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index df8b1cb07b..48d20cd17f 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -10,13 +10,16 @@ use Appwrite\Extend\Exception; use Appwrite\Hooks\Hooks; use Appwrite\Network\Validator\Email; use Appwrite\Network\Validator\Origin; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\ProjectId; use Appwrite\Utopia\Database\Validator\Queries\Projects; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use PHPMailer\PHPMailer\PHPMailer; -use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Cache\Cache; @@ -61,13 +64,20 @@ App::post('/v1/projects') ->desc('Create project') ->groups(['api', 'projects']) ->label('audits.event', 'projects.create') + ->label('audits.resource', 'project/{response.$id}') ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'create') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'create', + description: '/docs/references/projects/create.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new ProjectId(), '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.') ->param('name', null, new Text(128), 'Project name. Max length: 128 chars.') ->param('teamId', '', new UID(), 'Team unique ID.') @@ -83,13 +93,13 @@ App::post('/v1/projects') ->param('legalTaxId', '', new Text(256), 'Project legal Tax ID. Max length: 256 chars.', true) ->inject('request') ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('cache') ->inject('pools') ->inject('hooks') - ->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Request $request, Response $response, Database $dbForConsole, Cache $cache, Group $pools, Hooks $hooks) { + ->action(function (string $projectId, string $name, string $teamId, string $region, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Request $request, Response $response, Database $dbForPlatform, Cache $cache, Group $pools, Hooks $hooks) { - $team = $dbForConsole->getDocument('teams', $teamId); + $team = $dbForPlatform->getDocument('teams', $teamId); if ($team->isEmpty()) { throw new Exception(Exception::TEAM_NOT_FOUND); @@ -122,6 +132,10 @@ App::post('/v1/projects') $projectId = ($projectId == 'unique()') ? ID::unique() : $projectId; + if ($projectId === 'console') { + throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project."); + } + $databases = Config::getParam('pools-database', []); $databaseOverride = System::getEnv('_APP_DATABASE_OVERRIDE'); @@ -132,16 +146,14 @@ App::post('/v1/projects') $dsn = $databases[array_rand($databases)]; } - if ($projectId === 'console') { - throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project."); - } - // TODO: Temporary until all projects are using shared tables. - if ($dsn === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn, $sharedTables)) { $schema = 'appwrite'; $database = 'appwrite'; $namespace = System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); - $dsn = $schema . '://' . System::getEnv('_APP_DATABASE_SHARED_TABLES', '') . '?database=' . $database; + $dsn = $schema . '://' . $dsn . '?database=' . $database; if (!empty($namespace)) { $dsn .= '&namespace=' . $namespace; @@ -149,7 +161,7 @@ App::post('/v1/projects') } try { - $project = $dbForConsole->createDocument('projects', new Document([ + $project = $dbForPlatform->createDocument('projects', new Document([ '$id' => $projectId, '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -195,47 +207,78 @@ App::post('/v1/projects') $adapter = $pools->get($dsn->getHost())->pop()->getResource(); $dbForProject = new Database($adapter, $cache); + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + $sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', '')); - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { - $dbForProject - ->setSharedTables(true) - ->setTenant($project->getInternalId()) - ->setNamespace($dsn->getParam('namespace')); - } else { - $dbForProject - ->setSharedTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } + $projectTables = !\in_array($dsn->getHost(), $sharedTables); + $sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1); + $sharedTablesV2 = !$projectTables && !$sharedTablesV1; + $sharedTables = $sharedTablesV1 || $sharedTablesV2; - $dbForProject->create(); - - $audit = new Audit($dbForProject); - $audit->setup(); - - $abuse = new TimeLimit('', 0, 1, $dbForProject); - $abuse->setup(); - - /** @var array $collections */ - $collections = Config::getParam('collections', [])['projects'] ?? []; - - foreach ($collections as $key => $collection) { - if (($collection['$collection'] ?? '') !== Database::METADATA) { - continue; + if (!$sharedTablesV2) { + if ($sharedTables) { + $dbForProject + ->setSharedTables(true) + ->setTenant($sharedTablesV1 ? $project->getInternalId() : null) + ->setNamespace($dsn->getParam('namespace')); + } else { + $dbForProject + ->setSharedTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); } - $attributes = \array_map(function (array $attribute) { - return new Document($attribute); - }, $collection['attributes']); - - $indexes = \array_map(function (array $index) { - return new Document($index); - }, $collection['indexes']); + $create = true; try { - $dbForProject->createCollection($key, $attributes, $indexes); + $dbForProject->create(); } catch (Duplicate) { - // Collection already exists + $create = false; + } + + if ($create || $projectTables) { + $audit = new Audit($dbForProject); + $audit->setup(); + } + + if (!$create && $sharedTablesV1) { + $attributes = \array_map(fn ($attribute) => new Document($attribute), Audit::ATTRIBUTES); + $indexes = \array_map(fn (array $index) => new Document($index), Audit::INDEXES); + $dbForProject->createDocument(Database::METADATA, new Document([ + '$id' => ID::custom('audit'), + '$permissions' => [Permission::create(Role::any())], + 'name' => 'audit', + 'attributes' => $attributes, + 'indexes' => $indexes, + 'documentSecurity' => true + ])); + } + + if ($create || $sharedTablesV1) { + /** @var array $collections */ + $collections = Config::getParam('collections', [])['projects'] ?? []; + + foreach ($collections as $key => $collection) { + if (($collection['$collection'] ?? '') !== Database::METADATA) { + continue; + } + + $attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']); + $indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']); + + try { + $dbForProject->createCollection($key, $attributes, $indexes); + } catch (Duplicate) { + $dbForProject->createDocument(Database::METADATA, new Document([ + '$id' => ID::custom($key), + '$permissions' => [Permission::create(Role::any())], + 'name' => $key, + 'attributes' => $attributes, + 'indexes' => $indexes, + 'documentSecurity' => true + ])); + } + } } } @@ -252,17 +295,23 @@ App::get('/v1/projects') ->desc('List projects') ->groups(['api', 'projects']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'list') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT_LIST) + ->label('sdk', new Method( + namespace: 'projects', + name: 'list', + description: '/docs/references/projects/list.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT_LIST, + ) + ] + )) ->param('queries', [], new Projects(), '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(', ', Projects::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (array $queries, string $search, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (array $queries, string $search, Response $response, Database $dbForPlatform) { try { $queries = Query::parseQueries($queries); @@ -290,7 +339,7 @@ App::get('/v1/projects') } $projectId = $cursor->getValue(); - $cursorDocument = $dbForConsole->getDocument('projects', $projectId); + $cursorDocument = $dbForPlatform->getDocument('projects', $projectId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Project '{$projectId}' for the 'cursor' value not found."); @@ -302,8 +351,8 @@ App::get('/v1/projects') $filterQueries = Query::groupByType($queries)['filters']; $response->dynamic(new Document([ - 'projects' => $dbForConsole->find('projects', $queries), - 'total' => $dbForConsole->count('projects', $filterQueries, APP_LIMIT_COUNT), + 'projects' => $dbForPlatform->find('projects', $queries), + 'total' => $dbForPlatform->count('projects', $filterQueries, APP_LIMIT_COUNT), ]), Response::MODEL_PROJECT_LIST); }); @@ -311,18 +360,24 @@ App::get('/v1/projects/:projectId') ->desc('Get project') ->groups(['api', 'projects']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'get') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'get', + description: '/docs/references/projects/get.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -335,12 +390,20 @@ App::patch('/v1/projects/:projectId') ->desc('Update project') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'update') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('audits.event', 'projects.update') + ->label('audits.resource', 'project/{request.projectId}') + ->label('sdk', new Method( + namespace: 'projects', + name: 'update', + description: '/docs/references/projects/update.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('name', null, new Text(128), 'Project name. Max length: 128 chars.') ->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true) @@ -353,16 +416,16 @@ App::patch('/v1/projects/:projectId') ->param('legalAddress', '', new Text(256), 'Project legal address. Max length: 256 chars.', true) ->param('legalTaxId', '', new Text(256), 'Project legal tax ID. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $name, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $name, string $description, string $logo, string $url, string $legalName, string $legalCountry, string $legalState, string $legalCity, string $legalAddress, string $legalTaxId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('name', $name) ->setAttribute('description', $description) ->setAttribute('logo', $logo) @@ -382,20 +445,26 @@ App::patch('/v1/projects/:projectId/team') ->desc('Update project team') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateTeam') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateTeam', + description: '/docs/references/projects/update-team.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('teamId', '', new UID(), 'Team ID of the team to transfer project to.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $teamId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $teamId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); - $team = $dbForConsole->getDocument('teams', $teamId); + $project = $dbForPlatform->getDocument('projects', $projectId); + $team = $dbForPlatform->getDocument('teams', $teamId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -417,30 +486,30 @@ App::patch('/v1/projects/:projectId/team') ->setAttribute('teamId', $teamId) ->setAttribute('teamInternalId', $team->getInternalId()) ->setAttribute('$permissions', $permissions); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project); - $installations = $dbForConsole->find('installations', [ + $installations = $dbForPlatform->find('installations', [ Query::equal('projectInternalId', [$project->getInternalId()]), ]); foreach ($installations as $installation) { $installation->getAttribute('$permissions', $permissions); - $dbForConsole->updateDocument('installations', $installation->getId(), $installation); + $dbForPlatform->updateDocument('installations', $installation->getId(), $installation); } - $repositories = $dbForConsole->find('repositories', [ + $repositories = $dbForPlatform->find('repositories', [ Query::equal('projectInternalId', [$project->getInternalId()]), ]); foreach ($repositories as $repository) { $repository->getAttribute('$permissions', $permissions); - $dbForConsole->updateDocument('repositories', $repository->getId(), $repository); + $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository); } - $vcsComments = $dbForConsole->find('vcsComments', [ + $vcsComments = $dbForPlatform->find('vcsComments', [ Query::equal('projectInternalId', [$project->getInternalId()]), ]); foreach ($vcsComments as $vcsComment) { $vcsComment->getAttribute('$permissions', $permissions); - $dbForConsole->updateDocument('vcsComments', $vcsComment->getId(), $vcsComment); + $dbForPlatform->updateDocument('vcsComments', $vcsComment->getId(), $vcsComment); } $response->dynamic($project, Response::MODEL_PROJECT); @@ -450,20 +519,26 @@ App::patch('/v1/projects/:projectId/service') ->desc('Update service status') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateServiceStatus') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateServiceStatus', + description: '/docs/references/projects/update-service-status.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('service', '', new WhiteList(array_keys(array_filter(Config::getParam('services'), fn ($element) => $element['optional'])), true), 'Service name.') ->param('status', null, new Boolean(), 'Service status.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $service, bool $status, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $service, bool $status, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -472,7 +547,7 @@ App::patch('/v1/projects/:projectId/service') $services = $project->getAttribute('services', []); $services[$service] = $status; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('services', $services)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('services', $services)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -481,19 +556,25 @@ App::patch('/v1/projects/:projectId/service/all') ->desc('Update all service status') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateServiceStatusAll') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateServiceStatusAll', + description: '/docs/references/projects/update-service-status-all.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('status', null, new Boolean(), 'Service status.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $status, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $status, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -506,7 +587,7 @@ App::patch('/v1/projects/:projectId/service/all') $services[$service] = $status; } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('services', $services)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('services', $services)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -515,20 +596,26 @@ App::patch('/v1/projects/:projectId/api') ->desc('Update API status') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateApiStatus') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateApiStatus', + description: '/docs/references/projects/update-api-status.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('api', '', new WhiteList(array_keys(Config::getParam('apis')), true), 'API name.') ->param('status', null, new Boolean(), 'API status.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $api, bool $status, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $api, bool $status, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -537,7 +624,7 @@ App::patch('/v1/projects/:projectId/api') $apis = $project->getAttribute('apis', []); $apis[$api] = $status; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('apis', $apis)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('apis', $apis)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -546,19 +633,25 @@ App::patch('/v1/projects/:projectId/api/all') ->desc('Update all API status') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateApiStatusAll') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateApiStatusAll', + description: '/docs/references/projects/update-api-status-all.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('status', null, new Boolean(), 'API status.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $status, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $status, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -571,7 +664,7 @@ App::patch('/v1/projects/:projectId/api/all') $apis[$api] = $status; } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('apis', $apis)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('apis', $apis)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -580,22 +673,28 @@ App::patch('/v1/projects/:projectId/oauth2') ->desc('Update project OAuth2') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateOAuth2') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateOAuth2', + description: '/docs/references/projects/update-oauth2.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'Provider Name') ->param('appId', null, new Text(256), 'Provider app ID. Max length: 256 chars.', true) ->param('secret', null, new text(512), 'Provider secret key. Max length: 512 chars.', true) ->param('enabled', null, new Boolean(), 'Provider status. Set to \'false\' to disable new session creation.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $provider, ?string $appId, ?string $secret, ?bool $enabled, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $provider, ?string $appId, ?string $secret, ?bool $enabled, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -615,7 +714,7 @@ App::patch('/v1/projects/:projectId/oauth2') $providers[$provider . 'Enabled'] = $enabled; } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('oAuthProviders', $providers)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('oAuthProviders', $providers)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -624,19 +723,25 @@ App::patch('/v1/projects/:projectId/auth/session-alerts') ->desc('Update project sessions emails') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateSessionAlerts') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateSessionAlerts', + description: '/docs/references/projects/update-session-alerts.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('alerts', false, new Boolean(true), 'Set to true to enable session emails.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $alerts, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $alerts, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -645,7 +750,7 @@ App::patch('/v1/projects/:projectId/auth/session-alerts') $auths = $project->getAttribute('auths', []); $auths['sessionAlerts'] = $alerts; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -655,20 +760,26 @@ App::patch('/v1/projects/:projectId/auth/memberships-privacy') ->desc('Update project memberships privacy attributes') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateMembershipsPrivacy') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateMembershipsPrivacy', + description: '/docs/references/projects/update-memberships-privacy.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('userName', true, new Boolean(true), 'Set to true to show userName to members of a team.') ->param('userEmail', true, new Boolean(true), 'Set to true to show email to members of a team.') ->param('mfa', true, new Boolean(true), 'Set to true to show mfa to members of a team.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $userName, bool $userEmail, bool $mfa, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $userName, bool $userEmail, bool $mfa, Response $response, Database $dbForPlatform) { + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -680,7 +791,7 @@ App::patch('/v1/projects/:projectId/auth/memberships-privacy') $auths['membershipsUserEmail'] = $userEmail; $auths['membershipsMfa'] = $mfa; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -690,19 +801,25 @@ App::patch('/v1/projects/:projectId/auth/limit') ->desc('Update project users limit') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthLimit') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthLimit', + description: '/docs/references/projects/update-auth-limit.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('limit', false, new Range(0, APP_LIMIT_USERS), 'Set the max number of users allowed in this project. Use 0 for unlimited.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, int $limit, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -711,7 +828,7 @@ App::patch('/v1/projects/:projectId/auth/limit') $auths = $project->getAttribute('auths', []); $auths['limit'] = $limit; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -721,19 +838,25 @@ App::patch('/v1/projects/:projectId/auth/duration') ->desc('Update project authentication duration') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthDuration') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthDuration', + description: '/docs/references/projects/update-auth-duration.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('duration', 31536000, new Range(0, 31536000), 'Project session length in seconds. Max length: 31536000 seconds.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, int $duration, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, int $duration, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -742,7 +865,7 @@ App::patch('/v1/projects/:projectId/auth/duration') $auths = $project->getAttribute('auths', []); $auths['duration'] = $duration; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -752,20 +875,26 @@ App::patch('/v1/projects/:projectId/auth/:method') ->desc('Update project auth method status. Use this endpoint to enable or disable a given auth method for this project.') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthStatus') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthStatus', + description: '/docs/references/projects/update-auth-status.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: ' . implode(',', \array_keys(Config::getParam('auth'))), false) ->param('status', false, new Boolean(true), 'Set the status of this auth method.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $method, bool $status, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $method, bool $status, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); $auth = Config::getParam('auth')[$method] ?? []; $authKey = $auth['key'] ?? ''; $status = ($status === '1' || $status === 'true' || $status === 1 || $status === true); @@ -777,7 +906,7 @@ App::patch('/v1/projects/:projectId/auth/:method') $auths = $project->getAttribute('auths', []); $auths[$authKey] = $status; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -786,19 +915,25 @@ App::patch('/v1/projects/:projectId/auth/password-history') ->desc('Update authentication password history. Use this endpoint to set the number of password history to save and 0 to disable password history.') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthPasswordHistory') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthPasswordHistory', + description: '/docs/references/projects/update-auth-password-history.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('limit', 0, new Range(0, APP_LIMIT_USER_PASSWORD_HISTORY), '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 is' . APP_LIMIT_USER_PASSWORD_HISTORY . '. Default value is 0') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, int $limit, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -807,7 +942,7 @@ App::patch('/v1/projects/:projectId/auth/password-history') $auths = $project->getAttribute('auths', []); $auths['passwordHistory'] = $limit; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -817,19 +952,25 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary') ->desc('Update authentication password dictionary status. Use this endpoint to enable or disable the dicitonary check for user password') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthPasswordDictionary') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthPasswordDictionary', + description: '/docs/references/projects/update-auth-password-dictionary.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('enabled', false, new Boolean(false), 'Set whether or not to enable checking user\'s password against most commonly used passwords. Default is false.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -838,7 +979,7 @@ App::patch('/v1/projects/:projectId/auth/password-dictionary') $auths = $project->getAttribute('auths', []); $auths['passwordDictionary'] = $enabled; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -848,19 +989,25 @@ App::patch('/v1/projects/:projectId/auth/personal-data') ->desc('Enable or disable checking user passwords for similarity with their personal data.') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updatePersonalDataCheck') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updatePersonalDataCheck', + description: '/docs/references/projects/update-personal-data-check.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('enabled', false, new Boolean(false), 'Set whether or not to check a password for similarity with personal data. Default is false.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $enabled, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -869,7 +1016,7 @@ App::patch('/v1/projects/:projectId/auth/personal-data') $auths = $project->getAttribute('auths', []); $auths['personalDataCheck'] = $enabled; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -879,19 +1026,25 @@ App::patch('/v1/projects/:projectId/auth/max-sessions') ->desc('Update project user sessions limit') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateAuthSessionsLimit') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateAuthSessionsLimit', + description: '/docs/references/projects/update-auth-sessions-limit.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('limit', false, new Range(1, APP_LIMIT_USER_SESSIONS_MAX), 'Set the max number of users allowed in this project. Value allowed is between 1-' . APP_LIMIT_USER_SESSIONS_MAX . '. Default is ' . APP_LIMIT_USER_SESSIONS_DEFAULT) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, int $limit, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, int $limit, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -900,7 +1053,7 @@ App::patch('/v1/projects/:projectId/auth/max-sessions') $auths = $project->getAttribute('auths', []); $auths['maxSessions'] = $limit; - $dbForConsole->updateDocument('projects', $project->getId(), $project + $dbForPlatform->updateDocument('projects', $project->getId(), $project ->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); @@ -910,17 +1063,23 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers') ->desc('Update the mock numbers for the project') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateMockNumbers') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateMockNumbers', + description: '/docs/references/projects/update-mock-numbers.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('numbers', '', new ArrayList(new MockNumber(), 10), '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.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, array $numbers, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, array $numbers, Response $response, Database $dbForPlatform) { $uniqueNumbers = []; foreach ($numbers as $number) { @@ -930,7 +1089,7 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers') $uniqueNumbers[$number['phone']] = $number['otp']; } - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -940,7 +1099,7 @@ App::patch('/v1/projects/:projectId/auth/mock-numbers') $auths['mockNumbers'] = $numbers; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -949,19 +1108,28 @@ App::delete('/v1/projects/:projectId') ->desc('Delete project') ->groups(['api', 'projects']) ->label('audits.event', 'projects.delete') + ->label('audits.resource', 'project/{request.projectId}') ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'delete') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'delete', + description: '/docs/references/projects/delete.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') ->inject('user') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForDeletes') - ->action(function (string $projectId, Response $response, Document $user, Database $dbForConsole, Delete $queueForDeletes) { - $project = $dbForConsole->getDocument('projects', $projectId); + ->action(function (string $projectId, Response $response, Document $user, Database $dbForPlatform, Delete $queueForDeletes) { + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -972,7 +1140,7 @@ App::delete('/v1/projects/:projectId') ->setType(DELETE_TYPE_DOCUMENT) ->setDocument($project); - if (!$dbForConsole->deleteDocument('projects', $projectId)) { + if (!$dbForPlatform->deleteDocument('projects', $projectId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove project from DB'); } @@ -985,12 +1153,18 @@ App::post('/v1/projects/:projectId/webhooks') ->desc('Create webhook') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'createWebhook') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_WEBHOOK) + ->label('sdk', new Method( + namespace: 'projects', + name: 'createWebhook', + description: '/docs/references/projects/create-webhook.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_WEBHOOK, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') ->param('enabled', true, new Boolean(true), 'Enable or disable a webhook.', true) @@ -1000,10 +1174,10 @@ App::post('/v1/projects/:projectId/webhooks') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) ->param('httpPass', '', new Text(256), 'Webhook HTTP password. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1030,9 +1204,9 @@ App::post('/v1/projects/:projectId/webhooks') 'enabled' => $enabled, ]); - $webhook = $dbForConsole->createDocument('webhooks', $webhook); + $webhook = $dbForPlatform->createDocument('webhooks', $webhook); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -1043,24 +1217,30 @@ App::get('/v1/projects/:projectId/webhooks') ->desc('List webhooks') ->groups(['api', 'projects']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'listWebhooks') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_WEBHOOK_LIST) + ->label('sdk', new Method( + namespace: 'projects', + name: 'listWebhooks', + description: '/docs/references/projects/list-webhooks.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_WEBHOOK_LIST, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $webhooks = $dbForConsole->find('webhooks', [ + $webhooks = $dbForPlatform->find('webhooks', [ Query::equal('projectInternalId', [$project->getInternalId()]), Query::limit(5000), ]); @@ -1075,25 +1255,31 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Get webhook') ->groups(['api', 'projects']) ->label('scope', 'projects.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'getWebhook') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_WEBHOOK) + ->label('sdk', new Method( + namespace: 'projects', + name: 'getWebhook', + description: '/docs/references/projects/get-webhook.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_WEBHOOK, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $webhook = $dbForConsole->findOne('webhooks', [ + $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1109,12 +1295,18 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Update webhook') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateWebhook') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_WEBHOOK) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateWebhook', + description: '/docs/references/projects/update-webhook.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_WEBHOOK, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.') @@ -1125,10 +1317,10 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') ->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true) ->param('httpPass', '', new Text(256), 'Webhook HTTP password. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $webhookId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $webhookId, string $name, bool $enabled, array $events, string $url, bool $security, string $httpUser, string $httpPass, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1136,7 +1328,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $security = ($security === '1' || $security === 'true' || $security === 1 || $security === true); - $webhook = $dbForConsole->findOne('webhooks', [ + $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1158,8 +1350,8 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $webhook->setAttribute('attempts', 0); } - $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->dynamic($webhook, Response::MODEL_WEBHOOK); }); @@ -1168,25 +1360,31 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') ->desc('Update webhook signature key') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateWebhookSignature') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_WEBHOOK) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateWebhookSignature', + description: '/docs/references/projects/update-webhook-signature.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_WEBHOOK, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $webhook = $dbForConsole->findOne('webhooks', [ + $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1197,8 +1395,8 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') $webhook->setAttribute('signatureKey', \bin2hex(\random_bytes(64))); - $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->dynamic($webhook, Response::MODEL_WEBHOOK); }); @@ -1207,24 +1405,32 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') ->desc('Delete webhook') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'deleteWebhook') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'deleteWebhook', + description: '/docs/references/projects/delete-webhook.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('webhookId', '', new UID(), 'Webhook unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $webhookId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $webhook = $dbForConsole->findOne('webhooks', [ + $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1233,9 +1439,9 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') throw new Exception(Exception::WEBHOOK_NOT_FOUND); } - $dbForConsole->deleteDocument('webhooks', $webhook->getId()); + $dbForPlatform->deleteDocument('webhooks', $webhook->getId()); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1246,21 +1452,27 @@ App::post('/v1/projects/:projectId/keys') ->desc('Create key') ->groups(['api', 'projects']) ->label('scope', 'keys.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'createKey') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_KEY) + ->label('sdk', new Method( + namespace: 'projects', + name: 'createKey', + description: '/docs/references/projects/create-key.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_KEY, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.') ->param('expire', null, new DatetimeValidator(), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1283,9 +1495,9 @@ App::post('/v1/projects/:projectId/keys') 'secret' => API_KEY_STANDARD . '_' . \bin2hex(\random_bytes(128)), ]); - $key = $dbForConsole->createDocument('keys', $key); + $key = $dbForPlatform->createDocument('keys', $key); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -1296,24 +1508,30 @@ App::get('/v1/projects/:projectId/keys') ->desc('List keys') ->groups(['api', 'projects']) ->label('scope', 'keys.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'listKeys') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_KEY_LIST) + ->label('sdk', new Method( + namespace: 'projects', + name: 'listKeys', + description: '/docs/references/projects/list-keys.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_KEY_LIST, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $keys = $dbForConsole->find('keys', [ + $keys = $dbForPlatform->find('keys', [ Query::equal('projectInternalId', [$project->getInternalId()]), Query::limit(5000), ]); @@ -1328,25 +1546,31 @@ App::get('/v1/projects/:projectId/keys/:keyId') ->desc('Get key') ->groups(['api', 'projects']) ->label('scope', 'keys.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'getKey') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_KEY) + ->label('sdk', new Method( + namespace: 'projects', + name: 'getKey', + description: '/docs/references/projects/get-key.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_KEY, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('keyId', '', new UID(), 'Key unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $keyId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $keyId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $key = $dbForConsole->findOne('keys', [ + $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1362,28 +1586,34 @@ App::put('/v1/projects/:projectId/keys/:keyId') ->desc('Update key') ->groups(['api', 'projects']) ->label('scope', 'keys.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateKey') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_KEY) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateKey', + description: '/docs/references/projects/update-key.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_KEY, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('keyId', '', new UID(), 'Key unique ID.') ->param('name', null, new Text(128), 'Key name. Max length: 128 chars.') ->param('scopes', null, new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Key scopes list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.') ->param('expire', null, new DatetimeValidator(), 'Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $keyId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $keyId, string $name, array $scopes, ?string $expire, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $key = $dbForConsole->findOne('keys', [ + $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1397,9 +1627,9 @@ App::put('/v1/projects/:projectId/keys/:keyId') ->setAttribute('scopes', $scopes) ->setAttribute('expire', $expire); - $dbForConsole->updateDocument('keys', $key->getId(), $key); + $dbForPlatform->updateDocument('keys', $key->getId(), $key); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->dynamic($key, Response::MODEL_KEY); }); @@ -1408,24 +1638,32 @@ App::delete('/v1/projects/:projectId/keys/:keyId') ->desc('Delete key') ->groups(['api', 'projects']) ->label('scope', 'keys.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'deleteKey') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'deleteKey', + description: '/docs/references/projects/delete-key.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('keyId', '', new UID(), 'Key unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $keyId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $keyId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $key = $dbForConsole->findOne('keys', [ + $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1434,9 +1672,9 @@ App::delete('/v1/projects/:projectId/keys/:keyId') throw new Exception(Exception::KEY_NOT_FOUND); } - $dbForConsole->deleteDocument('keys', $key->getId()); + $dbForPlatform->deleteDocument('keys', $key->getId()); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1447,20 +1685,26 @@ App::post('/v1/projects/:projectId/jwts') ->groups(['api', 'projects']) ->desc('Create JWT') ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'createJWT') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_JWT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'createJWT', + description: '/docs/references/projects/create-jwt.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_JWT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('scopes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of scopes allowed for JWT key. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.') ->param('duration', 900, new Range(0, 3600), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, array $scopes, int $duration, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, array $scopes, int $duration, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1482,13 +1726,20 @@ App::post('/v1/projects/:projectId/platforms') ->desc('Create platform') ->groups(['api', 'projects']) ->label('audits.event', 'platforms.create') + ->label('audits.resource', 'project/{request.projectId}') ->label('scope', 'platforms.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'createPlatform') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PLATFORM) + ->label('sdk', new Method( + namespace: 'projects', + name: 'createPlatform', + description: '/docs/references/projects/create-platform.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PLATFORM, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', null, new WhiteList([Origin::CLIENT_TYPE_WEB, Origin::CLIENT_TYPE_FLUTTER_WEB, Origin::CLIENT_TYPE_FLUTTER_IOS, Origin::CLIENT_TYPE_FLUTTER_ANDROID, Origin::CLIENT_TYPE_FLUTTER_LINUX, Origin::CLIENT_TYPE_FLUTTER_MACOS, Origin::CLIENT_TYPE_FLUTTER_WINDOWS, Origin::CLIENT_TYPE_APPLE_IOS, Origin::CLIENT_TYPE_APPLE_MACOS, Origin::CLIENT_TYPE_APPLE_WATCHOS, Origin::CLIENT_TYPE_APPLE_TVOS, Origin::CLIENT_TYPE_ANDROID, Origin::CLIENT_TYPE_UNITY, Origin::CLIENT_TYPE_REACT_NATIVE_IOS, Origin::CLIENT_TYPE_REACT_NATIVE_ANDROID], true), 'Platform type.') ->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.') @@ -1496,9 +1747,9 @@ App::post('/v1/projects/:projectId/platforms') ->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true) ->param('hostname', '', new Hostname(), 'Platform client hostname. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $name, string $key, string $store, string $hostname, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $name, string $key, string $store, string $hostname, Response $response, Database $dbForPlatform) { + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1520,9 +1771,9 @@ App::post('/v1/projects/:projectId/platforms') 'hostname' => $hostname ]); - $platform = $dbForConsole->createDocument('platforms', $platform); + $platform = $dbForPlatform->createDocument('platforms', $platform); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -1533,24 +1784,30 @@ App::get('/v1/projects/:projectId/platforms') ->desc('List platforms') ->groups(['api', 'projects']) ->label('scope', 'platforms.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'listPlatforms') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PLATFORM_LIST) + ->label('sdk', new Method( + namespace: 'projects', + name: 'listPlatforms', + description: '/docs/references/projects/list-platforms.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PLATFORM_LIST, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $platforms = $dbForConsole->find('platforms', [ + $platforms = $dbForPlatform->find('platforms', [ Query::equal('projectInternalId', [$project->getInternalId()]), Query::limit(5000), ]); @@ -1565,25 +1822,31 @@ App::get('/v1/projects/:projectId/platforms/:platformId') ->desc('Get platform') ->groups(['api', 'projects']) ->label('scope', 'platforms.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'getPlatform') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PLATFORM) + ->label('sdk', new Method( + namespace: 'projects', + name: 'getPlatform', + description: '/docs/references/projects/get-platform.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PLATFORM, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('platformId', '', new UID(), 'Platform unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $platformId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $platformId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $platform = $dbForConsole->findOne('platforms', [ + $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1599,12 +1862,18 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->desc('Update platform') ->groups(['api', 'projects']) ->label('scope', 'platforms.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updatePlatform') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PLATFORM) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updatePlatform', + description: '/docs/references/projects/update-platform.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PLATFORM, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('platformId', '', new UID(), 'Platform unique ID.') ->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.') @@ -1612,15 +1881,15 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true) ->param('hostname', '', new Hostname(), 'Platform client URL. Max length: 256 chars.', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $platformId, string $name, string $key, string $store, string $hostname, Response $response, Database $dbForConsole) { - $project = $dbForConsole->getDocument('projects', $projectId); + ->inject('dbForPlatform') + ->action(function (string $projectId, string $platformId, string $name, string $key, string $store, string $hostname, Response $response, Database $dbForPlatform) { + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $platform = $dbForConsole->findOne('platforms', [ + $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1635,9 +1904,9 @@ App::put('/v1/projects/:projectId/platforms/:platformId') ->setAttribute('store', $store) ->setAttribute('hostname', $hostname); - $dbForConsole->updateDocument('platforms', $platform->getId(), $platform); + $dbForPlatform->updateDocument('platforms', $platform->getId(), $platform); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->dynamic($platform, Response::MODEL_PLATFORM); }); @@ -1646,25 +1915,34 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') ->desc('Delete platform') ->groups(['api', 'projects']) ->label('audits.event', 'platforms.delete') + ->label('audits.resource', 'project/{request.projectId}/platform/${request.platformId}') ->label('scope', 'platforms.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'deletePlatform') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'deletePlatform', + description: '/docs/references/projects/delete-platform.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('platformId', '', new UID(), 'Platform unique ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $platformId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $platformId, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - $platform = $dbForConsole->findOne('platforms', [ + $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), Query::equal('projectInternalId', [$project->getInternalId()]), ]); @@ -1673,9 +1951,9 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') throw new Exception(Exception::PLATFORM_NOT_FOUND); } - $dbForConsole->deleteDocument('platforms', $platformId); + $dbForPlatform->deleteDocument('platforms', $platformId); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response->noContent(); }); @@ -1686,12 +1964,18 @@ App::patch('/v1/projects/:projectId/smtp') ->desc('Update SMTP') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateSmtp') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateSmtp', + description: '/docs/references/projects/update-smtp.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROJECT, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('enabled', false, new Boolean(), 'Enable custom SMTP service') ->param('senderName', '', new Text(255, 0), 'Name of the email sender', true) @@ -1703,10 +1987,10 @@ App::patch('/v1/projects/:projectId/smtp') ->param('password', '', new Text(0, 0), 'SMTP server password', true) ->param('secure', '', new WhiteList(['tls', 'ssl'], true), 'Does SMTP server use secure connection', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, bool $enabled, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, bool $enabled, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1767,7 +2051,7 @@ App::patch('/v1/projects/:projectId/smtp') ]; } - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('smtp', $smtp)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('smtp', $smtp)); $response->dynamic($project, Response::MODEL_PROJECT); }); @@ -1776,11 +2060,18 @@ App::post('/v1/projects/:projectId/smtp/tests') ->desc('Create SMTP test') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'createSmtpTest') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'createSmtpTest', + description: '/docs/references/projects/create-smtp-test.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('emails', [], new ArrayList(new Email(), 10), 'Array of emails to send test email to. Maximum of 10 emails are allowed.') ->param('senderName', System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'), new Text(255, 0), 'Name of the email sender') @@ -1792,10 +2083,10 @@ App::post('/v1/projects/:projectId/smtp/tests') ->param('password', '', new Text(0, 0), 'SMTP server password', true) ->param('secure', '', new WhiteList(['tls', 'ssl'], true), 'Does SMTP server use secure connection', true) ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForMails') - ->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForConsole, Mail $queueForMails) { - $project = $dbForConsole->getDocument('projects', $projectId); + ->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform, Mail $queueForMails) { + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1835,22 +2126,28 @@ App::get('/v1/projects/:projectId/templates/sms/:type/:locale') ->desc('Get custom SMS template') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'getSmsTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'getSmsTemplate', + description: '/docs/references/projects/get-sms-template.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SMS_TEMPLATE, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForPlatform) { throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1876,20 +2173,26 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') ->desc('Get custom email template') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'getEmailTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'getEmailTemplate', + description: '/docs/references/projects/get-email-template.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EMAIL_TEMPLATE, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1928,23 +2231,29 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale') ->desc('Update custom SMS template') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateSmsTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateSmsTemplate', + description: '/docs/references/projects/update-sms-template.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SMS_TEMPLATE, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->param('message', '', new Text(0), 'Template message') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, string $message, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, string $message, Response $response, Database $dbForPlatform) { throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -1955,7 +2264,7 @@ App::patch('/v1/projects/:projectId/templates/sms/:type/:locale') 'message' => $message ]; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); $response->dynamic(new Document([ 'message' => $message, @@ -1968,12 +2277,18 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->desc('Update custom email templates') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'updateEmailTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROJECT) + ->label('sdk', new Method( + namespace: 'projects', + name: 'updateEmailTemplate', + description: '/docs/references/projects/update-email-template.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EMAIL_TEMPLATE, + ) + ] + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) @@ -1983,10 +2298,10 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') ->param('senderEmail', '', new Email(), 'Email of the sender', true) ->param('replyTo', '', new Email(), 'Reply to email', true) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, string $subject, string $message, string $senderName, string $senderEmail, string $replyTo, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, string $subject, string $message, string $senderName, string $senderEmail, string $replyTo, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -2001,7 +2316,7 @@ App::patch('/v1/projects/:projectId/templates/email/:type/:locale') 'message' => $message ]; - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); $response->dynamic(new Document([ 'type' => $type, @@ -2018,22 +2333,29 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale') ->desc('Reset custom SMS template') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'deleteSmsTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'deleteSmsTemplate', + description: '/docs/references/projects/delete-sms-template.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SMS_TEMPLATE, + ) + ], + contentType: ContentType::JSON + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForPlatform) { throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -2048,7 +2370,7 @@ App::delete('/v1/projects/:projectId/templates/sms/:type/:locale') unset($template['sms.' . $type . '-' . $locale]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); $response->dynamic(new Document([ 'type' => $type, @@ -2061,20 +2383,27 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') ->desc('Reset custom email template') ->groups(['api', 'projects']) ->label('scope', 'projects.write') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'projects') - ->label('sdk.method', 'deleteEmailTemplate') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) + ->label('sdk', new Method( + namespace: 'projects', + name: 'deleteEmailTemplate', + description: '/docs/references/projects/delete-email-template.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EMAIL_TEMPLATE, + ) + ], + contentType: ContentType::JSON + )) ->param('projectId', '', new UID(), 'Project unique ID.') ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') ->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForPlatform) { - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -2089,7 +2418,7 @@ App::delete('/v1/projects/:projectId/templates/email/:type/:locale') unset($templates['email.' . $type . '-' . $locale]); - $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); + $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); $response->dynamic(new Document([ 'type' => $type, diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 56fd31e88c..d8e637725a 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -4,7 +4,11 @@ use Appwrite\Event\Certificate; use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Extend\Exception; -use Appwrite\Network\Validator\CNAME; +use Appwrite\Network\Validator\DNS; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Rules; use Appwrite\Utopia\Response; use Utopia\App; @@ -17,152 +21,32 @@ use Utopia\Database\Validator\UID; use Utopia\Domains\Domain; use Utopia\Logger\Log; use Utopia\System\System; -use Utopia\Validator\Domain as ValidatorDomain; +use Utopia\Validator\AnyOf; +use Utopia\Validator\IP; use Utopia\Validator\Text; -use Utopia\Validator\WhiteList; - -App::post('/v1/proxy/rules') - ->groups(['api', 'proxy']) - ->desc('Create rule') - ->label('scope', 'rules.write') - ->label('event', 'rules.[ruleId].create') - ->label('audits.event', 'rule.create') - ->label('audits.resource', 'rule/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'proxy') - ->label('sdk.method', 'createRule') - ->label('sdk.description', '/docs/references/proxy/create-rule.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROXY_RULE) - ->param('domain', null, new ValidatorDomain(), 'Domain name.') - ->param('resourceType', null, new WhiteList(['api', 'function']), 'Action definition for the rule. Possible values are "api", "function"') - ->param('resourceId', '', new UID(), 'ID of resource for the action type. If resourceType is "api", leave empty. If resourceType is "function", provide ID of the function.', true) - ->inject('response') - ->inject('project') - ->inject('queueForCertificates') - ->inject('queueForEvents') - ->inject('dbForConsole') - ->inject('dbForProject') - ->action(function (string $domain, string $resourceType, string $resourceId, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForConsole, Database $dbForProject) { - $mainDomain = System::getEnv('_APP_DOMAIN', ''); - if ($domain === $mainDomain) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your main domain to specific resource. Please use subdomain or a different domain.'); - } - - $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); - if ($functionsDomain != '' && str_ends_with($domain, $functionsDomain)) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'You cannot assign your functions domain or it\'s subdomain to specific resource. Please use different domain.'); - } - - if ($domain === 'localhost' || $domain === APP_HOSTNAME_INTERNAL) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.'); - } - - $ruleId = md5($domain); - $document = $dbForConsole->getDocument('rules', $ruleId); - - if (!$document->isEmpty()) { - if ($document->getAttribute('projectId') === $project->getId()) { - $resourceType = $document->getAttribute('resourceType'); - $resourceId = $document->getAttribute('resourceId'); - $message = "Domain already assigned to '{$resourceType}' service"; - if (!empty($resourceId)) { - $message .= " with ID '{$resourceId}'"; - } - - $message .= '.'; - } else { - $message = 'Domain already assigned to different project.'; - } - - throw new Exception(Exception::RULE_ALREADY_EXISTS, $message); - } - - $resourceInternalId = ''; - - if ($resourceType == 'function') { - if (empty($resourceId)) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $function = $dbForProject->getDocument('functions', $resourceId); - - if ($function->isEmpty()) { - throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND); - } - - $resourceInternalId = $function->getInternalId(); - } - - try { - $domain = new Domain($domain); - } catch (\Throwable) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); - } - - $ruleId = md5($domain->get()); - $rule = new Document([ - '$id' => $ruleId, - 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), - 'domain' => $domain->get(), - 'resourceType' => $resourceType, - 'resourceId' => $resourceId, - 'resourceInternalId' => $resourceInternalId, - 'certificateId' => '', - ]); - - $status = 'created'; - $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS'); - if (!empty($functionsDomain) && \str_ends_with($domain->get(), $functionsDomain)) { - $status = 'verified'; - } - - if ($status === 'created') { - $target = new Domain(System::getEnv('_APP_DOMAIN_TARGET', '')); - $validator = new CNAME($target->get()); // Verify Domain with DNS records - - if ($validator->isValid($domain->get())) { - $status = 'verifying'; - - $queueForCertificates - ->setDomain(new Document([ - 'domain' => $rule->getAttribute('domain') - ])) - ->trigger(); - } - } - - $rule->setAttribute('status', $status); - $rule = $dbForConsole->createDocument('rules', $rule); - - $queueForEvents->setParam('ruleId', $rule->getId()); - - $rule->setAttribute('logs', ''); - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->dynamic($rule, Response::MODEL_PROXY_RULE); - }); App::get('/v1/proxy/rules') ->groups(['api', 'proxy']) ->desc('List rules') ->label('scope', 'rules.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'proxy') - ->label('sdk.method', 'listRules') - ->label('sdk.description', '/docs/references/proxy/list-rules.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROXY_RULE_LIST) + ->label('sdk', new Method( + namespace: 'proxy', + name: 'listRules', + description: '/docs/references/proxy/list-rules.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROXY_RULE_LIST, + ) + ] + )) ->param('queries', [], new Rules(), '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 ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Rules::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (array $queries, string $search, Response $response, Document $project, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (array $queries, string $search, Response $response, Document $project, Database $dbForPlatform) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -191,7 +75,7 @@ App::get('/v1/proxy/rules') } $ruleId = $cursor->getValue(); - $cursorDocument = $dbForConsole->getDocument('rules', $ruleId); + $cursorDocument = $dbForPlatform->getDocument('rules', $ruleId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Rule '{$ruleId}' for the 'cursor' value not found."); @@ -202,16 +86,16 @@ App::get('/v1/proxy/rules') $filterQueries = Query::groupByType($queries)['filters']; - $rules = $dbForConsole->find('rules', $queries); + $rules = $dbForPlatform->find('rules', $queries); foreach ($rules as $rule) { - $certificate = $dbForConsole->getDocument('certificates', $rule->getAttribute('certificateId', '')); + $certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', '')); $rule->setAttribute('logs', $certificate->getAttribute('logs', '')); $rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', '')); } $response->dynamic(new Document([ 'rules' => $rules, - 'total' => $dbForConsole->count('rules', $filterQueries, APP_LIMIT_COUNT), + 'total' => $dbForPlatform->count('rules', $filterQueries, APP_LIMIT_COUNT), ]), Response::MODEL_PROXY_RULE_LIST); }); @@ -219,25 +103,30 @@ App::get('/v1/proxy/rules/:ruleId') ->groups(['api', 'proxy']) ->desc('Get rule') ->label('scope', 'rules.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'proxy') - ->label('sdk.method', 'getRule') - ->label('sdk.description', '/docs/references/proxy/get-rule.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROXY_RULE) + ->label('sdk', new Method( + namespace: 'proxy', + name: 'getRule', + description: '/docs/references/proxy/get-rule.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROXY_RULE, + ) + ] + )) ->param('ruleId', '', new UID(), 'Rule ID.') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $ruleId, Response $response, Document $project, Database $dbForConsole) { - $rule = $dbForConsole->getDocument('rules', $ruleId); + ->inject('dbForPlatform') + ->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform) { + $rule = $dbForPlatform->getDocument('rules', $ruleId); if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::RULE_NOT_FOUND); } - $certificate = $dbForConsole->getDocument('certificates', $rule->getAttribute('certificateId', '')); + $certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', '')); $rule->setAttribute('logs', $certificate->getAttribute('logs', '')); $rule->setAttribute('renewAt', $certificate->getAttribute('renewDate', '')); @@ -251,26 +140,33 @@ App::delete('/v1/proxy/rules/:ruleId') ->label('event', 'rules.[ruleId].delete') ->label('audits.event', 'rules.delete') ->label('audits.resource', 'rule/{request.ruleId}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'proxy') - ->label('sdk.method', 'deleteRule') - ->label('sdk.description', '/docs/references/proxy/delete-rule.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'proxy', + name: 'deleteRule', + description: '/docs/references/proxy/delete-rule.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('ruleId', '', new UID(), 'Rule ID.') ->inject('response') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForDeletes') ->inject('queueForEvents') - ->action(function (string $ruleId, Response $response, Document $project, Database $dbForConsole, Delete $queueForDeletes, Event $queueForEvents) { - $rule = $dbForConsole->getDocument('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()) { throw new Exception(Exception::RULE_NOT_FOUND); } - $dbForConsole->deleteDocument('rules', $rule->getId()); + $dbForPlatform->deleteDocument('rules', $rule->getId()); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) @@ -288,37 +184,53 @@ App::patch('/v1/proxy/rules/:ruleId/verification') ->label('event', 'rules.[ruleId].update') ->label('audits.event', 'rule.update') ->label('audits.resource', 'rule/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'proxy') - ->label('sdk.method', 'updateRuleVerification') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROXY_RULE) + ->label('sdk', new Method( + namespace: 'proxy', + name: 'updateRuleVerification', + description: '/docs/references/proxy/update-rule-verification.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROXY_RULE, + ) + ] + )) ->param('ruleId', '', new UID(), 'Rule ID.') ->inject('response') ->inject('queueForCertificates') ->inject('queueForEvents') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('log') - ->action(function (string $ruleId, Response $response, Certificate $queueForCertificates, Event $queueForEvents, Document $project, Database $dbForConsole, Log $log) { - $rule = $dbForConsole->getDocument('rules', $ruleId); + ->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()) { throw new Exception(Exception::RULE_NOT_FOUND); } - $target = new Domain(System::getEnv('_APP_DOMAIN_TARGET', '')); + $validators = []; + $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')); + 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); + } + if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) { + $validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA); + } - if (!$target->isKnown() || $target->isTest()) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Domain target must be configured as environment variable.'); + if (empty($validators)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.'); } if ($rule->getAttribute('verification') === true) { return $response->dynamic($rule, Response::MODEL_PROXY_RULE); } - $validator = new CNAME($target->get()); // Verify Domain with DNS records + $validator = new AnyOf($validators, AnyOf::TYPE_STRING); $domain = new Domain($rule->getAttribute('domain', '')); $validationStart = \microtime(true); @@ -326,13 +238,20 @@ App::patch('/v1/proxy/rules/:ruleId/verification') $log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart)); $log->addTag('dnsDomain', $domain->get()); - $error = $validator->getLogs(); + $errors = []; + foreach ($validators as $validator) { + if (!empty($validator->getLogs())) { + $errors[] = $validator->getLogs(); + } + } + + $error = \implode("\n", $errors); $log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error)); throw new Exception(Exception::RULE_VERIFICATION_FAILED); } - $dbForConsole->updateDocument('rules', $rule->getId(), $rule->setAttribute('status', 'verifying')); + $dbForPlatform->updateDocument('rules', $rule->getId(), $rule->setAttribute('status', 'verifying')); // Issue a TLS certificate when domain is verified $queueForCertificates @@ -343,7 +262,7 @@ App::patch('/v1/proxy/rules/:ruleId/verification') $queueForEvents->setParam('ruleId', $rule->getId()); - $certificate = $dbForConsole->getDocument('certificates', $rule->getAttribute('certificateId', '')); + $certificate = $dbForPlatform->getDocument('certificates', $rule->getAttribute('certificateId', '')); $rule->setAttribute('logs', $certificate->getAttribute('logs', '')); $response->dynamic($rule, Response::MODEL_PROXY_RULE); diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index dda39a0db0..f13c9703c5 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -8,6 +8,11 @@ use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Extend\Exception; use Appwrite\OpenSSL\OpenSSL; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Buckets; use Appwrite\Utopia\Database\Validator\Queries\Files; @@ -15,6 +20,7 @@ use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Config\Config; use Utopia\Database\Database; +use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\NotFound as NotFoundException; @@ -54,13 +60,18 @@ App::post('/v1/storage/buckets') ->label('event', 'buckets.[bucketId].create') ->label('audits.event', 'bucket.create') ->label('audits.resource', 'bucket/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'createBucket') - ->label('sdk.description', '/docs/references/storage/create-bucket.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUCKET) + ->label('sdk', new Method( + namespace: 'storage', + name: 'createBucket', + description: '/docs/references/storage/create-bucket.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_BUCKET, + ) + ] + )) ->param('bucketId', '', new CustomId(), '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.') ->param('name', '', new Text(128), 'Bucket name') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) @@ -68,19 +79,20 @@ App::post('/v1/storage/buckets') ->param('enabled', true, new Boolean(true), '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.', true) ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) - ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) + ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD], true), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, int $maximumFileSize, array $allowedFileExtensions, ?string $compression, ?bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { $bucketId = $bucketId === 'unique()' ? ID::unique() : $bucketId; // Map aggregate permissions into the multiple permissions they represent. $permissions = Permission::aggregate($permissions); - + $compression ??= Compression::NONE; + $encryption ??= true; try { $files = (Config::getParam('collections', [])['buckets'] ?? [])['files'] ?? []; if (empty($files)) { @@ -150,13 +162,18 @@ App::get('/v1/storage/buckets') ->groups(['api', 'storage']) ->label('scope', 'buckets.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'listBuckets') - ->label('sdk.description', '/docs/references/storage/list-buckets.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUCKET_LIST) + ->label('sdk', new Method( + namespace: 'storage', + name: 'listBuckets', + description: '/docs/references/storage/list-buckets.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_BUCKET_LIST, + ) + ] + )) ->param('queries', [], new Buckets(), '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(', ', Buckets::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -211,13 +228,18 @@ App::get('/v1/storage/buckets/:bucketId') ->groups(['api', 'storage']) ->label('scope', 'buckets.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getBucket') - ->label('sdk.description', '/docs/references/storage/get-bucket.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUCKET) + ->label('sdk', new Method( + namespace: 'storage', + name: 'getBucket', + description: '/docs/references/storage/get-bucket.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_BUCKET, + ) + ] + )) ->param('bucketId', '', new UID(), 'Bucket unique ID.') ->inject('response') ->inject('dbForProject') @@ -240,13 +262,18 @@ App::put('/v1/storage/buckets/:bucketId') ->label('event', 'buckets.[bucketId].update') ->label('audits.event', 'bucket.update') ->label('audits.resource', 'bucket/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'updateBucket') - ->label('sdk.description', '/docs/references/storage/update-bucket.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUCKET) + ->label('sdk', new Method( + namespace: 'storage', + name: 'updateBucket', + description: '/docs/references/storage/update-bucket.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_BUCKET, + ) + ] + )) ->param('bucketId', '', new UID(), 'Bucket unique ID.') ->param('name', null, new Text(128), 'Bucket name', false) ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) @@ -254,13 +281,13 @@ App::put('/v1/storage/buckets/:bucketId') ->param('enabled', true, new Boolean(true), '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.', true) ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) - ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) + ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD], true), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) ->param('antivirus', true, new Boolean(true), 'Is virus scanning enabled? For file size above ' . Storage::human(APP_LIMIT_ANTIVIRUS, 0) . ' AntiVirus scanning is skipped even if it\'s enabled', true) ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, string $compression, bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $bucketId, string $name, ?array $permissions, bool $fileSecurity, bool $enabled, ?int $maximumFileSize, array $allowedFileExtensions, ?string $compression, ?bool $encryption, bool $antivirus, Response $response, Database $dbForProject, Event $queueForEvents) { $bucket = $dbForProject->getDocument('buckets', $bucketId); if ($bucket->isEmpty()) { @@ -273,6 +300,7 @@ App::put('/v1/storage/buckets/:bucketId') $enabled ??= $bucket->getAttribute('enabled', true); $encryption ??= $bucket->getAttribute('encryption', true); $antivirus ??= $bucket->getAttribute('antivirus', true); + $compression ??= $bucket->getAttribute('compression', Compression::NONE); // Map aggregate permissions into the multiple permissions they represent. $permissions = Permission::aggregate($permissions); @@ -304,12 +332,19 @@ App::delete('/v1/storage/buckets/:bucketId') ->label('audits.event', 'bucket.delete') ->label('event', 'buckets.[bucketId].delete') ->label('audits.resource', 'bucket/{request.bucketId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'deleteBucket') - ->label('sdk.description', '/docs/references/storage/delete-bucket.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'deleteBucket', + description: '/docs/references/storage/delete-bucket.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('bucketId', '', new UID(), 'Bucket unique ID.') ->inject('response') ->inject('dbForProject') @@ -350,15 +385,20 @@ App::post('/v1/storage/buckets/:bucketId/files') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId},chunkId:{chunkId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'createFile') - ->label('sdk.description', '/docs/references/storage/create-file.md') - ->label('sdk.request.type', 'multipart/form-data') - ->label('sdk.methodType', 'upload') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FILE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'createFile', + description: '/docs/references/storage/create-file.md', + type: MethodType::UPLOAD, + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + requestType: 'multipart/form-data', + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_FILE, + ) + ] + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new CustomId(), '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.') ->param('file', [], new File(), 'Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https://appwrite.io/docs/products/storage/upload-download#input-file).', skipValidation: true) @@ -714,13 +754,18 @@ App::get('/v1/storage/buckets/:bucketId/files') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'listFiles') - ->label('sdk.description', '/docs/references/storage/list-files.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FILE_LIST) + ->label('sdk', new Method( + namespace: 'storage', + name: 'listFiles', + description: '/docs/references/storage/list-files.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FILE_LIST, + ) + ] + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('queries', [], new Files(), '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(', ', Files::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) @@ -806,13 +851,18 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getFile') - ->label('sdk.description', '/docs/references/storage/get-file.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FILE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'getFile', + description: '/docs/references/storage/get-file.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FILE, + ) + ] + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File ID.') ->inject('response') @@ -857,13 +907,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->label('cache', true) ->label('cache.resourceType', 'bucket/{request.bucketId}') ->label('cache.resource', 'file/{request.fileId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getFilePreview') - ->label('sdk.description', '/docs/references/storage/get-file-preview.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_IMAGE) - ->label('sdk.methodType', 'location') + ->label('sdk', new Method( + namespace: 'storage', + name: 'getFilePreview', + description: '/docs/references/storage/get-file-preview.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE + ) + ], + type: MethodType::LOCATION, + contentType: ContentType::IMAGE + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File ID') ->param('width', 0, new Range(0, 4000), 'Resize preview image width, Pass an integer between 0 to 4000.', true) @@ -877,14 +934,11 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') ->param('rotation', 0, new Range(-360, 360), 'Preview image rotation in degrees. Pass an integer between -360 and 360.', true) ->param('background', '', new HexColor(), 'Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.', true) ->param('output', '', new WhiteList(\array_keys(Config::getParam('storage-outputs')), true), 'Output format type (jpeg, jpg, png, gif and webp).', true) - ->inject('request') ->inject('response') - ->inject('project') ->inject('dbForProject') - ->inject('mode') ->inject('deviceForFiles') ->inject('deviceForLocal') - ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, string $mode, Device $deviceForFiles, Device $deviceForLocal) { + ->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Response $response, Database $dbForProject, Device $deviceForFiles, Device $deviceForLocal) { if (!\extension_loaded('imagick')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing'); @@ -1012,11 +1066,19 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $contentType = (\array_key_exists($output, $outputs)) ? $outputs[$output] : $outputs['jpg']; + //Do not update transformedAt if it's a console user + if (!Auth::isPrivilegedUser(Authorization::getRoles())) { + $transformedAt = $file->getAttribute('transformedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { + $file->setAttribute('transformedAt', DateTime::now()); + Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + } + } + $response ->addHeader('Cache-Control', 'private, max-age=2592000') // 30 days ->setContentType($contentType) - ->file($data) - ; + ->file($data); unset($image); }); @@ -1027,13 +1089,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getFileDownload') - ->label('sdk.description', '/docs/references/storage/get-file-download.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', '*/*') - ->label('sdk.methodType', 'location') + ->label('sdk', new Method( + namespace: 'storage', + name: 'getFileDownload', + description: '/docs/references/storage/get-file-download.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE + ) + ], + type: MethodType::LOCATION, + contentType: ContentType::ANY, + )) ->param('bucketId', '', new UID(), 'Storage bucket ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File ID.') ->inject('request') @@ -1168,13 +1237,20 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getFileView') - ->label('sdk.description', '/docs/references/storage/get-file-view.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', '*/*') - ->label('sdk.methodType', 'location') + ->label('sdk', new Method( + namespace: 'storage', + name: 'getFileView', + description: '/docs/references/storage/get-file-view.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + type: MethodType::LOCATION, + contentType: ContentType::ANY, + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File ID.') ->inject('response') @@ -1481,13 +1557,18 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'updateFile') - ->label('sdk.description', '/docs/references/storage/update-file.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_FILE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'updateFile', + description: '/docs/references/storage/update-file.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FILE, + ) + ] + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File unique ID.') ->param('name', null, new Text(255), 'Name of the file', true) @@ -1590,12 +1671,19 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT) ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'deleteFile') - ->label('sdk.description', '/docs/references/storage/delete-file.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'deleteFile', + description: '/docs/references/storage/delete-file.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('bucketId', '', new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https://appwrite.io/docs/server/storage#createBucket).') ->param('fileId', '', new UID(), 'File ID.') ->inject('response') @@ -1682,12 +1770,18 @@ App::get('/v1/storage/usage') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_STORAGE) + ->label('sdk', new Method( + namespace: 'storage', + name: 'getUsage', + description: '/docs/references/storage/get-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_STORAGE, + ) + ] + )) ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') @@ -1762,18 +1856,27 @@ App::get('/v1/storage/:bucketId/usage') ->groups(['api', 'storage']) ->label('scope', 'files.read') ->label('resourceType', RESOURCE_TYPE_BUCKETS) - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'storage') - ->label('sdk.method', 'getBucketUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_BUCKETS) + ->label('sdk', new Method( + namespace: 'storage', + name: 'getBucketUsage', + description: '/docs/references/storage/get-bucket-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_BUCKETS, + ) + ] + )) ->param('bucketId', '', new UID(), 'Bucket ID.') ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') + ->inject('project') ->inject('dbForProject') - ->action(function (string $bucketId, string $range, Response $response, Database $dbForProject) { + ->inject('getLogsDB') + ->action(function (string $bucketId, string $range, Response $response, Document $project, Database $dbForProject, callable $getLogsDB) { + $dbForLogs = call_user_func($getLogsDB, $project); $bucket = $dbForProject->getDocument('buckets', $bucketId); if ($bucket->isEmpty()) { @@ -1786,12 +1889,16 @@ App::get('/v1/storage/:bucketId/usage') $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), ]; - - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats, &$total) { + Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $result = $dbForProject->findOne('stats', [ + $db = ($metric === str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) + ? $dbForLogs + : $dbForProject; + + $result = $db->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) ]); @@ -1799,7 +1906,7 @@ App::get('/v1/storage/:bucketId/usage') $stats[$metric]['total'] = $result['value'] ?? 0; $limit = $days['limit']; $period = $days['period']; - $results = $dbForProject->find('stats', [ + $results = $db->find('stats', [ Query::equal('metric', [$metric]), Query::equal('period', [$period]), Query::limit($limit), @@ -1840,5 +1947,7 @@ App::get('/v1/storage/:bucketId/usage') 'filesStorageTotal' => $usage[$metrics[1]]['total'], 'files' => $usage[$metrics[0]]['data'], 'storage' => $usage[$metrics[1]]['data'], + 'imageTransformations' => $usage[$metrics[2]]['data'], + 'imageTransformationsTotal' => $usage[$metrics[2]]['total'], ]), Response::MODEL_USAGE_BUCKETS); }); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index be055f0935..3e0e366b6b 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -8,16 +8,23 @@ use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Event\Mail; use Appwrite\Event\Messaging; +use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\Email; use Appwrite\Platform\Workers\Deletes; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Template\Template; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Memberships; use Appwrite\Utopia\Database\Validator\Queries\Teams; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; +use libphonenumber\PhoneNumberUtil; use MaxMind\Db\Reader; +use Utopia\Abuse\Abuse; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; @@ -53,13 +60,18 @@ App::post('/v1/teams') ->label('scope', 'teams.write') ->label('audits.event', 'team.create') ->label('audits.resource', 'team/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'create') - ->label('sdk.description', '/docs/references/teams/create-team.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEAM) + ->label('sdk', new Method( + namespace: 'teams', + name: 'create', + description: '/docs/references/teams/create-team.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TEAM, + ) + ] + )) ->param('teamId', '', new CustomId(), '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.') ->param('name', null, new Text(128), 'Team name. Max length: 128 chars.') ->param('roles', ['owner'], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), '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 ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', true) @@ -138,14 +150,18 @@ App::get('/v1/teams') ->desc('List teams') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'list') - ->label('sdk.description', '/docs/references/teams/list-teams.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEAM_LIST) - ->label('sdk.offline.model', '/teams') + ->label('sdk', new Method( + namespace: 'teams', + name: 'list', + description: '/docs/references/teams/list-teams.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEAM_LIST, + ) + ] + )) ->param('queries', [], new Teams(), '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(', ', Teams::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -202,15 +218,18 @@ App::get('/v1/teams/:teamId') ->desc('Get team') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/teams/get-team.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEAM) - ->label('sdk.offline.model', '/teams') - ->label('sdk.offline.key', '{teamId}') + ->label('sdk', new Method( + namespace: 'teams', + name: 'get', + description: '/docs/references/teams/get-team.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEAM, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->inject('response') ->inject('dbForProject') @@ -229,14 +248,18 @@ App::get('/v1/teams/:teamId/prefs') ->desc('Get team preferences') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'getPrefs') - ->label('sdk.description', '/docs/references/teams/get-team-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PREFERENCES) - ->label('sdk.offline.model', '/teams/{teamId}/prefs') + ->label('sdk', new Method( + namespace: 'teams', + name: 'getPrefs', + description: '/docs/references/teams/get-team-prefs.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PREFERENCES, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->inject('response') ->inject('dbForProject') @@ -260,15 +283,18 @@ App::put('/v1/teams/:teamId') ->label('scope', 'teams.write') ->label('audits.event', 'team.update') ->label('audits.resource', 'team/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'updateName') - ->label('sdk.description', '/docs/references/teams/update-team-name.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TEAM) - ->label('sdk.offline.model', '/teams') - ->label('sdk.offline.key', '{teamId}') + ->label('sdk', new Method( + namespace: 'teams', + name: 'updateName', + description: '/docs/references/teams/update-team-name.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEAM, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('name', null, new Text(128), 'New team name. Max length: 128 chars.') ->inject('requestTimestamp') @@ -304,14 +330,18 @@ App::put('/v1/teams/:teamId/prefs') ->label('audits.event', 'team.update') ->label('audits.resource', 'team/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'updatePrefs') - ->label('sdk.description', '/docs/references/teams/update-team-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PREFERENCES) - ->label('sdk.offline.model', '/teams/{teamId}/prefs') + ->label('sdk', new Method( + namespace: 'teams', + name: 'updatePrefs', + description: '/docs/references/teams/update-team-prefs.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PREFERENCES, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.') ->inject('response') @@ -339,12 +369,19 @@ App::delete('/v1/teams/:teamId') ->label('scope', 'teams.write') ->label('audits.event', 'team.delete') ->label('audits.resource', 'team/{request.teamId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/teams/delete-team.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'teams', + name: 'delete', + description: '/docs/references/teams/delete-team.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('teamId', '', new UID(), 'Team ID.') ->inject('response') ->inject('getProjectDB') @@ -390,13 +427,18 @@ App::post('/v1/teams/:teamId/memberships') ->label('audits.event', 'membership.create') ->label('audits.resource', 'team/{request.teamId}') ->label('audits.userId', '{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'createMembership') - ->label('sdk.description', '/docs/references/teams/create-team-membership.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP) + ->label('sdk', new Method( + namespace: 'teams', + name: 'createMembership', + description: '/docs/references/teams/create-team-membership.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MEMBERSHIP, + ) + ] + )) ->label('abuse-limit', 10) ->param('teamId', '', new UID(), 'Team ID.') ->param('email', '', new Email(), 'Email of the new team member.', true) @@ -423,13 +465,16 @@ App::post('/v1/teams/:teamId/memberships') ->inject('queueForMails') ->inject('queueForMessaging') ->inject('queueForEvents') - ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents) { - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + ->inject('timelimit') + ->inject('queueForStatsUsage') + ->inject('plan') + ->action(function (string $teamId, string $email, string $userId, string $phone, array $roles, string $url, string $name, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Mail $queueForMails, Messaging $queueForMessaging, Event $queueForEvents, callable $timelimit, StatsUsage $queueForStatsUsage, array $plan) { + $isAppUser = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); $url = htmlentities($url); if (empty($url)) { - if (!$isAPIKey && !$isPrivilegedUser) { + if (!$isAppUser && !$isPrivilegedUser) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'URL is required'); } } @@ -437,15 +482,13 @@ App::post('/v1/teams/:teamId/memberships') if (empty($userId) && empty($email) && empty($phone)) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'At least one of userId, email, or phone is required'); } - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - $isAppUser = Auth::isAppUser(Authorization::getRoles()); if (!$isPrivilegedUser && !$isAppUser && empty(System::getEnv('_APP_SMTP_HOST'))) { throw new Exception(Exception::GENERAL_SMTP_DISABLED); } $email = \strtolower($email); - $name = (empty($name)) ? $email : $name; + $name = empty($name) ? $email : $name; $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -464,7 +507,7 @@ App::post('/v1/teams/:teamId/memberships') } $email = $invitee->getAttribute('email', ''); $phone = $invitee->getAttribute('phone', ''); - $name = empty($name) ? $invitee->getAttribute('name', '') : $name; + $name = $invitee->getAttribute('name', '') ?: $name; } elseif (!empty($email)) { $invitee = $dbForProject->findOne('users', [Query::equal('email', [$email])]); // Get user by email address if (!$invitee->isEmpty() && !empty($phone) && $invitee->getAttribute('phone', '') !== $phone) { @@ -540,49 +583,64 @@ App::post('/v1/teams/:teamId/memberships') throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to send invitations for this team'); } - $secret = Auth::tokenGenerator(); - - $membershipId = ID::unique(); - $membership = new Document([ - '$id' => $membershipId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($invitee->getId())), - Permission::update(Role::team($team->getId(), 'owner')), - Permission::delete(Role::user($invitee->getId())), - Permission::delete(Role::team($team->getId(), 'owner')), - ], - 'userId' => $invitee->getId(), - 'userInternalId' => $invitee->getInternalId(), - 'teamId' => $team->getId(), - 'teamInternalId' => $team->getInternalId(), - 'roles' => $roles, - 'invited' => DateTime::now(), - 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, - 'confirm' => ($isPrivilegedUser || $isAppUser), - 'secret' => Auth::hash($secret), - 'search' => implode(' ', [$membershipId, $invitee->getId()]) + $membership = $dbForProject->findOne('memberships', [ + Query::equal('userInternalId', [$invitee->getInternalId()]), + Query::equal('teamInternalId', [$team->getInternalId()]), ]); - if ($isPrivilegedUser || $isAppUser) { // Allow admin to create membership - try { - $membership = Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)); - } catch (Duplicate $th) { - throw new Exception(Exception::TEAM_INVITE_ALREADY_EXISTS); + $secret = Auth::tokenGenerator(); + if ($membership->isEmpty()) { + $membershipId = ID::unique(); + $membership = new Document([ + '$id' => $membershipId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::user($invitee->getId())), + Permission::update(Role::team($team->getId(), 'owner')), + Permission::delete(Role::user($invitee->getId())), + Permission::delete(Role::team($team->getId(), 'owner')), + ], + 'userId' => $invitee->getId(), + 'userInternalId' => $invitee->getInternalId(), + 'teamId' => $team->getId(), + 'teamInternalId' => $team->getInternalId(), + 'roles' => $roles, + 'invited' => DateTime::now(), + 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, + 'confirm' => ($isPrivilegedUser || $isAppUser), + 'secret' => Auth::hash($secret), + 'search' => implode(' ', [$membershipId, $invitee->getId()]) + ]); + + $membership = ($isPrivilegedUser || $isAppUser) ? + Authorization::skip(fn () => $dbForProject->createDocument('memberships', $membership)) : + $dbForProject->createDocument('memberships', $membership); + + if ($isPrivilegedUser || $isAppUser) { + Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); } - Authorization::skip(fn () => $dbForProject->increaseDocumentAttribute('teams', $team->getId(), 'total', 1)); + } elseif ($membership->getAttribute('confirm') === false) { + $membership->setAttribute('secret', Auth::hash($secret)); + $membership->setAttribute('invited', DateTime::now()); + if ($isPrivilegedUser || $isAppUser) { + $membership->setAttribute('joined', DateTime::now()); + $membership->setAttribute('confirm', true); + } + + $membership = ($isPrivilegedUser || $isAppUser) ? + Authorization::skip(fn () => $dbForProject->updateDocument('memberships', $membership->getId(), $membership)) : + $dbForProject->updateDocument('memberships', $membership->getId(), $membership); + } else { + throw new Exception(Exception::MEMBERSHIP_ALREADY_CONFIRMED); + } + + if ($isPrivilegedUser || $isAppUser) { $dbForProject->purgeCachedDocument('users', $invitee->getId()); } else { - try { - $membership = $dbForProject->createDocument('memberships', $membership); - } catch (Duplicate $th) { - throw new Exception(Exception::TEAM_INVITE_ALREADY_EXISTS); - } - $url = Template::parseURL($url); - $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['membershipId' => $membership->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId]); + $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['membershipId' => $membership->getId(), 'userId' => $invitee->getId(), 'secret' => $secret, 'teamId' => $teamId, 'teamName' => $team->getAttribute('name')]); $url = Template::unParseURL($url); if (!empty($email)) { $projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]'); @@ -650,7 +708,7 @@ App::post('/v1/teams/:teamId/memberships') 'owner' => $user->getAttribute('name'), 'direction' => $locale->getText('settings.direction'), /* {{user}}, {{team}}, {{redirect}} and {{project}} are required in default and custom templates */ - 'user' => $user->getAttribute('name'), + 'user' => $name, 'team' => $team->getAttribute('name'), 'redirect' => $url, 'project' => $projectName @@ -660,10 +718,10 @@ App::post('/v1/teams/:teamId/memberships') ->setSubject($subject) ->setBody($body) ->setRecipient($invitee->getAttribute('email')) - ->setName($invitee->getAttribute('name')) + ->setName($invitee->getAttribute('name', '')) ->setVariables($emailVariables) - ->trigger() - ; + ->trigger(); + } elseif (!empty($phone)) { if (empty(System::getEnv('_APP_SMS_PROVIDER'))) { throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured'); @@ -691,6 +749,27 @@ App::post('/v1/teams/:teamId/memberships') ->setMessage($messageDoc) ->setRecipients([$phone]) ->setProviderType('SMS'); + + if (isset($plan['authPhone'])) { + $timelimit = $timelimit('organization:{organizationId}', $plan['authPhone'], 30 * 24 * 60 * 60); // 30 days + $timelimit + ->setParam('{organizationId}', $project->getAttribute('teamId')); + + $abuse = new Abuse($timelimit); + if ($abuse->check() && System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled') { + $helper = PhoneNumberUtil::getInstance(); + $countryCode = $helper->parse($phone)->getCountryCode(); + + if (!empty($countryCode)) { + $queueForStatsUsage + ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); + } + } + $queueForStatsUsage + ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) + ->setProject($project) + ->trigger(); + } } } @@ -715,14 +794,18 @@ App::get('/v1/teams/:teamId/memberships') ->desc('List team memberships') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'listMemberships') - ->label('sdk.description', '/docs/references/teams/list-team-members.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP_LIST) - ->label('sdk.offline.model', '/teams/{teamId}/memberships') + ->label('sdk', new Method( + namespace: 'teams', + name: 'listMemberships', + description: '/docs/references/teams/list-team-members.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MEMBERSHIP_LIST, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Memberships(), '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(', ', Memberships::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) @@ -805,8 +888,11 @@ App::get('/v1/teams/:teamId/memberships') }, $membershipsPrivacy); $memberships = array_map(function ($membership) use ($dbForProject, $team, $membershipsPrivacy) { + $user = !empty(array_filter($membershipsPrivacy)) + ? $dbForProject->getDocument('users', $membership->getAttribute('userId')) + : new Document(); + if ($membershipsPrivacy['mfa']) { - $user = $dbForProject->getDocument('users', $membership->getAttribute('userId')); $mfa = $user->getAttribute('mfa', false); if ($mfa) { @@ -846,15 +932,18 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') ->desc('Get team membership') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'getMembership') - ->label('sdk.description', '/docs/references/teams/get-team-member.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP) - ->label('sdk.offline.model', '/teams/{teamId}/memberships') - ->label('sdk.offline.key', '{membershipId}') + ->label('sdk', new Method( + namespace: 'teams', + name: 'getMembership', + description: '/docs/references/teams/get-team-member.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MEMBERSHIP, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') ->inject('response') @@ -888,9 +977,11 @@ App::get('/v1/teams/:teamId/memberships/:membershipId') return $privacy || $isPrivilegedUser || $isAppUser; }, $membershipsPrivacy); - if ($membershipsPrivacy['mfa']) { - $user = $dbForProject->getDocument('users', $membership->getAttribute('userId')); + $user = !empty(array_filter($membershipsPrivacy)) + ? $dbForProject->getDocument('users', $membership->getAttribute('userId')) + : new Document(); + if ($membershipsPrivacy['mfa']) { $mfa = $user->getAttribute('mfa', false); if ($mfa) { @@ -927,18 +1018,22 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ->label('scope', 'teams.write') ->label('audits.event', 'membership.update') ->label('audits.resource', 'team/{request.teamId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'updateMembership') - ->label('sdk.description', '/docs/references/teams/update-team-membership.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP) + ->label('sdk', new Method( + namespace: 'teams', + name: 'updateMembership', + description: '/docs/references/teams/update-team-membership.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MEMBERSHIP, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') ->param('roles', [], function (Document $project) { if ($project->getId() === 'console') { - ; $roles = array_keys(Config::getParam('roles', [])); array_filter($roles, function ($role) { return !in_array($role, [Auth::USER_ROLE_APPS, Auth::USER_ROLE_GUESTS, Auth::USER_ROLE_USERS]); @@ -950,9 +1045,10 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ->inject('request') ->inject('response') ->inject('user') + ->inject('project') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, array $roles, Request $request, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) { $team = $dbForProject->getDocument('teams', $teamId); if ($team->isEmpty()) { @@ -973,6 +1069,21 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') $isAppUser = Auth::isAppUser(Authorization::getRoles()); $isOwner = Authorization::isRole('team:' . $team->getId() . '/owner'); + 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'])], + max: 2 + ); + + // 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)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'There must be at least one owner in the organization.'); + } + } + if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server) throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to modify roles'); } @@ -1010,13 +1121,18 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->label('audits.event', 'membership.update') ->label('audits.resource', 'team/{request.teamId}') ->label('audits.userId', '{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'updateMembershipStatus') - ->label('sdk.description', '/docs/references/teams/update-team-membership-status.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP) + ->label('sdk', new Method( + namespace: 'teams', + name: 'updateMembershipStatus', + description: '/docs/references/teams/update-team-membership-status.md', + auth: [AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MEMBERSHIP, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') ->param('userId', '', new UID(), 'User ID.') @@ -1055,7 +1171,8 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')'); } - if ($user->isEmpty()) { + $hasSession = !$user->isEmpty(); + if (!$hasSession) { $user->setAttributes($dbForProject->getDocument('users', $userId)->getArrayCopy()); // Get user } @@ -1074,39 +1191,64 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') Authorization::skip(fn () => $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', true))); - // Log user in + // Create session for the user if not logged in + if (!$hasSession) { + Authorization::setRole(Role::user($user->getId())->toString()); - Authorization::setRole(Role::user($user->getId())->toString()); + $detector = new Detector($request->getUserAgent('UNKNOWN')); + $record = $geodb->get($request->getIP()); + $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; + $expire = DateTime::addSeconds(new \DateTime(), $authDuration); + $secret = Auth::tokenGenerator(); + $session = new Document(array_merge([ + '$id' => ID::unique(), + '$permissions' => [ + Permission::read(Role::user($user->getId())), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ], + 'userId' => $user->getId(), + 'userInternalId' => $user->getInternalId(), + 'provider' => Auth::SESSION_PROVIDER_EMAIL, + 'providerUid' => $user->getAttribute('email'), + 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak + 'userAgent' => $request->getUserAgent('UNKNOWN'), + 'ip' => $request->getIP(), + 'factors' => ['email'], + 'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--', + 'expire' => DateTime::addSeconds(new \DateTime(), $authDuration) + ], $detector->getOS(), $detector->getClient(), $detector->getDevice())); - $detector = new Detector($request->getUserAgent('UNKNOWN')); - $record = $geodb->get($request->getIP()); - $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; - $expire = DateTime::addSeconds(new \DateTime(), $authDuration); - $secret = Auth::tokenGenerator(); - $session = new Document(array_merge([ - '$id' => ID::unique(), - 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), - 'provider' => Auth::SESSION_PROVIDER_EMAIL, - 'providerUid' => $user->getAttribute('email'), - 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak - 'userAgent' => $request->getUserAgent('UNKNOWN'), - 'ip' => $request->getIP(), - 'factors' => ['email'], - 'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--', - 'expire' => DateTime::addSeconds(new \DateTime(), $authDuration) - ], $detector->getOS(), $detector->getClient(), $detector->getDevice())); + $session = $dbForProject->createDocument('sessions', $session); - $session = $dbForProject->createDocument('sessions', $session - ->setAttribute('$permissions', [ - Permission::read(Role::user($user->getId())), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ])); + Authorization::setRole(Role::user($userId)->toString()); - $dbForProject->purgeCachedDocument('users', $user->getId()); + if (!Config::getParam('domainVerification')) { + $response->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])); + } - Authorization::setRole(Role::user($userId)->toString()); + $response + ->addCookie( + name: Auth::$cookieName . '_legacy', + value: Auth::encodeSession($user->getId(), $secret), + expire: (new \DateTime($expire))->getTimestamp(), + path: '/', + domain: Config::getParam('cookieDomain'), + secure: ('https' === $protocol), + httponly: true + ) + ->addCookie( + name: Auth::$cookieName, + value: Auth::encodeSession($user->getId(), $secret), + expire: (new \DateTime($expire))->getTimestamp(), + path: '/', + domain: Config::getParam('cookieDomain'), + secure: ('https' === $protocol), + httponly: true, + sameSite: Config::getParam('cookieSamesite') + ) + ; + } $membership = $dbForProject->updateDocument('memberships', $membership->getId(), $membership); @@ -1120,22 +1262,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') ->setParam('membershipId', $membership->getId()) ; - if (!Config::getParam('domainVerification')) { - $response - ->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)])) - ; - } - - $response - ->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null) - ->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite')) - ; - $response->dynamic( $membership - ->setAttribute('teamName', $team->getAttribute('name')) - ->setAttribute('userName', $user->getAttribute('name')) - ->setAttribute('userEmail', $user->getAttribute('email')), + ->setAttribute('teamName', $team->getAttribute('name')) + ->setAttribute('userName', $user->getAttribute('name')) + ->setAttribute('userEmail', $user->getAttribute('email')), Response::MODEL_MEMBERSHIP ); }); @@ -1147,12 +1278,19 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') ->label('scope', 'teams.write') ->label('audits.event', 'membership.delete') ->label('audits.resource', 'team/{request.teamId}') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'deleteMembership') - ->label('sdk.description', '/docs/references/teams/delete-team-membership.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'teams', + name: 'deleteMembership', + description: '/docs/references/teams/delete-team-membership.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') ->inject('response') @@ -1210,13 +1348,18 @@ App::get('/v1/teams/:teamId/logs') ->desc('List team logs') ->groups(['api', 'teams']) ->label('scope', 'teams.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'teams') - ->label('sdk.method', 'listLogs') - ->label('sdk.description', '/docs/references/teams/get-team-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'teams', + name: 'listLogs', + description: '/docs/references/teams/get-team-logs.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ] + )) ->param('teamId', '', new UID(), 'Team ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), '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', true) ->inject('response') @@ -1237,13 +1380,15 @@ App::get('/v1/teams/:teamId/logs') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $grouped = Query::groupByType($queries); - $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; - $offset = $grouped['offset'] ?? 0; + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); $audit = new Audit($dbForProject); $resource = 'team/' . $team->getId(); - $logs = $audit->getLogsByResource($resource, $limit, $offset); + $logs = $audit->getLogsByResource($resource, $queries); $output = []; @@ -1290,7 +1435,7 @@ App::get('/v1/teams/:teamId/logs') } } $response->dynamic(new Document([ - 'total' => $audit->countLogsByResource($resource), + 'total' => $audit->countLogsByResource($resource, $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 42f7a59f54..17096731fa 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -15,8 +15,13 @@ use Appwrite\Event\Event; use Appwrite\Extend\Exception; use Appwrite\Hooks\Hooks; use Appwrite\Network\Validator\Email; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\CustomId; use Appwrite\Utopia\Database\Validator\Queries\Identities; +use Appwrite\Utopia\Database\Validator\Queries\Memberships; use Appwrite\Utopia\Database\Validator\Queries\Targets; use Appwrite\Utopia\Database\Validator\Queries\Users; use Appwrite\Utopia\Request; @@ -185,13 +190,18 @@ App::post('/v1/users') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'create') - ->label('sdk.description', '/docs/references/users/create-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'create', + description: '/docs/references/users/create-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), '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.') ->param('email', null, new Email(), 'User email.', true) ->param('phone', null, new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true) @@ -214,13 +224,18 @@ App::post('/v1/users/bcrypt') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createBcryptUser') - ->label('sdk.description', '/docs/references/users/create-bcrypt-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createBcryptUser', + description: '/docs/references/users/create-bcrypt-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), '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.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using Bcrypt.') @@ -243,13 +258,18 @@ App::post('/v1/users/md5') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createMD5User') - ->label('sdk.description', '/docs/references/users/create-md5-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createMD5User', + description: '/docs/references/users/create-md5-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), '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.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using MD5.') @@ -272,13 +292,18 @@ App::post('/v1/users/argon2') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createArgon2User') - ->label('sdk.description', '/docs/references/users/create-argon2-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createArgon2User', + description: '/docs/references/users/create-argon2-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), '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.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using Argon2.') @@ -301,13 +326,18 @@ App::post('/v1/users/sha') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createSHAUser') - ->label('sdk.description', '/docs/references/users/create-sha-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createSHAUser', + description: '/docs/references/users/create-sha-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), '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.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using SHA.') @@ -337,13 +367,18 @@ App::post('/v1/users/phpass') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createPHPassUser') - ->label('sdk.description', '/docs/references/users/create-phpass-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createPHPassUser', + description: '/docs/references/users/create-phpass-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), '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.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using PHPass.') @@ -366,13 +401,18 @@ App::post('/v1/users/scrypt') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createScryptUser') - ->label('sdk.description', '/docs/references/users/create-scrypt-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createScryptUser', + description: '/docs/references/users/create-scrypt-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), '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.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using Scrypt.') @@ -408,13 +448,18 @@ App::post('/v1/users/scrypt-modified') ->label('scope', 'users.write') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createScryptModifiedUser') - ->label('sdk.description', '/docs/references/users/create-scrypt-modified-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'createScryptModifiedUser', + description: '/docs/references/users/create-scrypt-modified-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new CustomId(), '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.') ->param('email', '', new Email(), 'User email.') ->param('password', '', new Password(), 'User password hashed using Scrypt Modified.') @@ -441,13 +486,18 @@ App::post('/v1/users/:userId/targets') ->label('audits.resource', 'target/response.$id') ->label('event', 'users.[userId].targets.[targetId].create') ->label('scope', 'targets.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createTarget') - ->label('sdk.description', '/docs/references/users/create-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'users', + name: 'createTarget', + description: '/docs/references/users/create-target.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TARGET, + ) + ] + )) ->param('targetId', '', new CustomId(), '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.') ->param('userId', '', new UID(), 'User ID.') ->param('providerType', '', new WhiteList([MESSAGE_TYPE_EMAIL, MESSAGE_TYPE_SMS, MESSAGE_TYPE_PUSH]), 'The target provider type. Can be one of the following: `email`, `sms` or `push`.') @@ -527,13 +577,18 @@ App::get('/v1/users') ->desc('List users') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'list') - ->label('sdk.description', '/docs/references/users/list-users.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'list', + description: '/docs/references/users/list-users.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER_LIST, + ) + ] + )) ->param('queries', [], new Users(), '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('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -587,13 +642,18 @@ App::get('/v1/users/:userId') ->desc('Get user') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'get') - ->label('sdk.description', '/docs/references/users/get-user.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'get', + description: '/docs/references/users/get-user.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -612,13 +672,18 @@ App::get('/v1/users/:userId/prefs') ->desc('Get user preferences') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'getPrefs') - ->label('sdk.description', '/docs/references/users/get-user-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PREFERENCES) + ->label('sdk', new Method( + namespace: 'users', + name: 'getPrefs', + description: '/docs/references/users/get-user-prefs.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PREFERENCES, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -639,13 +704,18 @@ App::get('/v1/users/:userId/targets/:targetId') ->desc('Get user target') ->groups(['api', 'users']) ->label('scope', 'targets.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'getTarget') - ->label('sdk.description', '/docs/references/users/get-user-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'users', + name: 'getTarget', + description: '/docs/references/users/get-user-target.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TARGET, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('targetId', '', new UID(), 'Target ID.') ->inject('response') @@ -671,13 +741,18 @@ App::get('/v1/users/:userId/sessions') ->desc('List user sessions') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listSessions') - ->label('sdk.description', '/docs/references/users/list-user-sessions.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'listSessions', + description: '/docs/references/users/list-user-sessions.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SESSION_LIST, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -712,17 +787,24 @@ App::get('/v1/users/:userId/memberships') ->desc('List user memberships') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listMemberships') - ->label('sdk.description', '/docs/references/users/list-user-memberships.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MEMBERSHIP_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'listMemberships', + description: '/docs/references/users/list-user-memberships.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MEMBERSHIP_LIST, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') + ->param('queries', [], new Memberships(), '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(', ', Memberships::ALLOWED_ATTRIBUTES), true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('dbForProject') - ->action(function (string $userId, Response $response, Database $dbForProject) { + ->action(function (string $userId, array $queries, string $search, Response $response, Database $dbForProject) { $user = $dbForProject->getDocument('users', $userId); @@ -730,6 +812,19 @@ App::get('/v1/users/:userId/memberships') throw new Exception(Exception::USER_NOT_FOUND); } + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + // Set internal queries + $queries[] = Query::equal('userInternalId', [$user->getInternalId()]); + $memberships = array_map(function ($membership) use ($dbForProject, $user) { $team = $dbForProject->getDocument('teams', $membership->getAttribute('teamId')); @@ -739,7 +834,7 @@ App::get('/v1/users/:userId/memberships') ->setAttribute('userEmail', $user->getAttribute('email')); return $membership; - }, $user->getAttribute('memberships', [])); + }, $dbForProject->find('memberships', $queries)); $response->dynamic(new Document([ 'memberships' => $memberships, @@ -751,13 +846,18 @@ App::get('/v1/users/:userId/logs') ->desc('List user logs') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listLogs') - ->label('sdk.description', '/docs/references/users/list-user-logs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_LOG_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'listLogs', + description: '/docs/references/users/list-user-logs.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_LOG_LIST, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('queries', [], new Queries([new Limit(), new Offset()]), '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', true) ->inject('response') @@ -778,13 +878,15 @@ App::get('/v1/users/:userId/logs') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $grouped = Query::groupByType($queries); - $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; - $offset = $grouped['offset'] ?? 0; + // Temp fix for logs + $queries[] = Query::or([ + Query::greaterThan('$createdAt', DateTime::format(new \DateTime('2025-02-26T01:30+00:00'))), + Query::lessThan('$createdAt', DateTime::format(new \DateTime('2025-02-13T00:00+00:00'))), + ]); $audit = new Audit($dbForProject); - $logs = $audit->getLogsByUser($user->getInternalId(), $limit, $offset); + $logs = $audit->getLogsByUser($user->getInternalId(), $queries); $output = []; @@ -831,7 +933,7 @@ App::get('/v1/users/:userId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getInternalId()), + 'total' => $audit->countLogsByUser($user->getInternalId(), $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -840,13 +942,18 @@ App::get('/v1/users/:userId/targets') ->desc('List user targets') ->groups(['api', 'users']) ->label('scope', 'targets.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listTargets') - ->label('sdk.description', '/docs/references/users/list-user-targets.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'listTargets', + description: '/docs/references/users/list-user-targets.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TARGET_LIST, + ) + ] + )) ->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) ->inject('response') @@ -900,13 +1007,18 @@ App::get('/v1/users/identities') ->desc('List identities') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listIdentities') - ->label('sdk.description', '/docs/references/users/list-identities.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_IDENTITY_LIST) + ->label('sdk', new Method( + namespace: 'users', + name: 'listIdentities', + description: '/docs/references/users/list-identities.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_IDENTITY_LIST, + ) + ] + )) ->param('queries', [], new Identities(), '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(', ', Identities::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') @@ -964,13 +1076,18 @@ App::patch('/v1/users/:userId/status') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateStatus') - ->label('sdk.description', '/docs/references/users/update-user-status.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateStatus', + description: '/docs/references/users/update-user-status.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('status', null, new Boolean(true), 'User Status. To activate the user pass `true` and to block the user pass `false`.') ->inject('response') @@ -999,13 +1116,18 @@ App::put('/v1/users/:userId/labels') ->label('scope', 'users.write') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateLabels') - ->label('sdk.description', '/docs/references/users/update-user-labels.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateLabels', + description: '/docs/references/users/update-user-labels.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('labels', [], new ArrayList(new Text(36, allowList: [...Text::NUMBERS, ...Text::ALPHABET_UPPER, ...Text::ALPHABET_LOWER]), APP_LIMIT_ARRAY_LABELS_SIZE), 'Array of user labels. Replaces the previous labels. Maximum of ' . APP_LIMIT_ARRAY_LABELS_SIZE . ' labels are allowed, each up to 36 alphanumeric characters long.') ->inject('response') @@ -1036,13 +1158,18 @@ App::patch('/v1/users/:userId/verification/phone') ->label('scope', 'users.write') ->label('audits.event', 'verification.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updatePhoneVerification') - ->label('sdk.description', '/docs/references/users/update-user-phone-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updatePhoneVerification', + description: '/docs/references/users/update-user-phone-verification.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('phoneVerification', false, new Boolean(), 'User phone verification status.') ->inject('response') @@ -1072,13 +1199,18 @@ App::patch('/v1/users/:userId/name') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateName') - ->label('sdk.description', '/docs/references/users/update-user-name.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateName', + description: '/docs/references/users/update-user-name.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('name', '', new Text(128, 0), 'User name. Max length: 128 chars.') ->inject('response') @@ -1109,13 +1241,18 @@ App::patch('/v1/users/:userId/password') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updatePassword') - ->label('sdk.description', '/docs/references/users/update-user-password.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updatePassword', + description: '/docs/references/users/update-user-password.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('password', '', fn ($project, $passwordsDictionary) => new PasswordDictionary($passwordsDictionary, enabled: $project->getAttribute('auths', [])['passwordDictionary'] ?? false, allowEmpty: true), 'New user password. Must be at least 8 chars.', false, ['project', 'passwordsDictionary']) ->inject('response') @@ -1186,13 +1323,18 @@ App::patch('/v1/users/:userId/email') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateEmail') - ->label('sdk.description', '/docs/references/users/update-user-email.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateEmail', + description: '/docs/references/users/update-user-email.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('email', '', new Email(allowEmpty: true), 'User email.') ->inject('response') @@ -1280,13 +1422,18 @@ App::patch('/v1/users/:userId/phone') ->label('scope', 'users.write') ->label('audits.event', 'user.update') ->label('audits.resource', 'user/{response.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updatePhone') - ->label('sdk.description', '/docs/references/users/update-user-phone.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updatePhone', + description: '/docs/references/users/update-user-phone.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('number', '', new Phone(allowEmpty: true), 'User phone number.') ->inject('response') @@ -1364,13 +1511,18 @@ App::patch('/v1/users/:userId/verification') ->label('audits.event', 'verification.update') ->label('audits.resource', 'user/{request.userId}') ->label('audits.userId', '{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateEmailVerification') - ->label('sdk.description', '/docs/references/users/update-user-email-verification.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateEmailVerification', + description: '/docs/references/users/update-user-email-verification.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('emailVerification', false, new Boolean(), 'User email verification status.') ->inject('response') @@ -1396,13 +1548,18 @@ App::patch('/v1/users/:userId/prefs') ->groups(['api', 'users']) ->label('event', 'users.[userId].update.prefs') ->label('scope', 'users.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updatePrefs') - ->label('sdk.description', '/docs/references/users/update-user-prefs.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PREFERENCES) + ->label('sdk', new Method( + namespace: 'users', + name: 'updatePrefs', + description: '/docs/references/users/update-user-prefs.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PREFERENCES, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.') ->inject('response') @@ -1431,13 +1588,18 @@ App::patch('/v1/users/:userId/targets/:targetId') ->label('audits.resource', 'target/{response.$id}') ->label('event', 'users.[userId].targets.[targetId].update') ->label('scope', 'targets.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateTarget') - ->label('sdk.description', '/docs/references/users/update-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TARGET) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateTarget', + description: '/docs/references/users/update-target.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TARGET, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('targetId', '', new UID(), 'Target ID.') ->param('identifier', '', new Text(Database::LENGTH_KEY), 'The target identifier (token, email, phone etc.)', true) @@ -1530,13 +1692,18 @@ App::patch('/v1/users/:userId/mfa') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') ->label('usage.metric', 'users.{scope}.requests.update') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateMfa') - ->label('sdk.description', '/docs/references/users/update-user-mfa.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateMfa', + description: '/docs/references/users/update-user-mfa.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USER, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('mfa', null, new Boolean(), 'Enable or disable MFA.') ->inject('response') @@ -1564,13 +1731,18 @@ App::get('/v1/users/:userId/mfa/factors') ->groups(['api', 'users']) ->label('scope', 'users.read') ->label('usage.metric', 'users.{scope}.requests.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'listMfaFactors') - ->label('sdk.description', '/docs/references/users/list-mfa-factors.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_FACTORS) + ->label('sdk', new Method( + namespace: 'users', + name: 'listMfaFactors', + description: '/docs/references/users/list-mfa-factors.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_FACTORS, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -1597,13 +1769,18 @@ App::get('/v1/users/:userId/mfa/recovery-codes') ->groups(['api', 'users']) ->label('scope', 'users.read') ->label('usage.metric', 'users.{scope}.requests.read') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'getMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/users/get-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) + ->label('sdk', new Method( + namespace: 'users', + name: 'getMfaRecoveryCodes', + description: '/docs/references/users/get-mfa-recovery-codes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -1636,13 +1813,18 @@ App::patch('/v1/users/:userId/mfa/recovery-codes') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') ->label('usage.metric', 'users.{scope}.requests.update') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/users/create-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) + ->label('sdk', new Method( + namespace: 'users', + name: 'createMfaRecoveryCodes', + description: '/docs/references/users/create-mfa-recovery-codes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -1682,13 +1864,18 @@ App::put('/v1/users/:userId/mfa/recovery-codes') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') ->label('usage.metric', 'users.{scope}.requests.update') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'updateMfaRecoveryCodes') - ->label('sdk.description', '/docs/references/users/update-mfa-recovery-codes.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_MFA_RECOVERY_CODES) + ->label('sdk', new Method( + namespace: 'users', + name: 'updateMfaRecoveryCodes', + description: '/docs/references/users/update-mfa-recovery-codes.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_MFA_RECOVERY_CODES, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -1727,13 +1914,19 @@ App::delete('/v1/users/:userId/mfa/authenticators/:type') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') ->label('usage.metric', 'users.{scope}.requests.update') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'deleteMfaAuthenticator') - ->label('sdk.description', '/docs/references/users/delete-mfa-authenticator.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USER) + ->label('sdk', new Method( + namespace: 'users', + name: 'deleteMfaAuthenticator', + description: '/docs/references/users/delete-mfa-authenticator.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('userId', '', new UID(), 'User ID.') ->param('type', null, new WhiteList([Type::TOTP]), 'Type of authenticator.') ->inject('response') @@ -1768,13 +1961,18 @@ App::post('/v1/users/:userId/sessions') ->label('audits.event', 'session.create') ->label('audits.resource', 'user/{request.userId}') ->label('usage.metric', 'sessions.{scope}.requests.create') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createSession') - ->label('sdk.description', '/docs/references/users/create-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_SESSION) + ->label('sdk', new Method( + namespace: 'users', + name: 'createSession', + description: '/docs/references/users/create-session.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SESSION, + ) + ] + )) ->param('userId', '', new CustomId(), '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.') ->inject('request') ->inject('response') @@ -1804,6 +2002,7 @@ App::post('/v1/users/:userId/sessions') 'provider' => Auth::SESSION_PROVIDER_SERVER, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), + 'factors' => ['server'], 'ip' => $request->getIP(), 'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--', 'expire' => $expire, @@ -1813,11 +2012,20 @@ App::post('/v1/users/:userId/sessions') $detector->getDevice() )); + $session->setAttribute('$permissions', [ + Permission::read(Role::user($user->getId())), + Permission::update(Role::user($user->getId())), + Permission::delete(Role::user($user->getId())), + ]); + $countryName = $locale->getText('countries.' . strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown')); $session = $dbForProject->createDocument('sessions', $session); + + $dbForProject->purgeCachedDocument('users', $user->getId()); + $session - ->setAttribute('secret', $secret) + ->setAttribute('secret', Auth::encodeSession($user->getId(), $secret)) ->setAttribute('countryName', $countryName); $queueForEvents @@ -1837,13 +2045,18 @@ App::post('/v1/users/:userId/tokens') ->label('scope', 'users.write') ->label('audits.event', 'tokens.create') ->label('audits.resource', 'user/{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createToken') - ->label('sdk.description', '/docs/references/users/create-token.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_TOKEN) + ->label('sdk', new Method( + namespace: 'users', + name: 'createToken', + description: '/docs/references/users/create-token.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_TOKEN, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('length', 6, new Range(4, 128), 'Token length in characters. The default length is 6 characters', true) ->param('expire', Auth::TOKEN_EXPIRATION_GENERIC, new Range(60, Auth::TOKEN_EXPIRATION_LOGIN_LONG), 'Token expiration period in seconds. The default expiration is 15 minutes.', true) @@ -1894,12 +2107,19 @@ App::delete('/v1/users/:userId/sessions/:sessionId') ->label('scope', 'users.write') ->label('audits.event', 'session.delete') ->label('audits.resource', 'user/{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'deleteSession') - ->label('sdk.description', '/docs/references/users/delete-user-session.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'users', + name: 'deleteSession', + description: '/docs/references/users/delete-user-session.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('userId', '', new UID(), 'User ID.') ->param('sessionId', '', new UID(), 'Session ID.') ->inject('response') @@ -1937,12 +2157,19 @@ App::delete('/v1/users/:userId/sessions') ->label('scope', 'users.write') ->label('audits.event', 'session.delete') ->label('audits.resource', 'user/{user.$id}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'deleteSessions') - ->label('sdk.description', '/docs/references/users/delete-user-sessions.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'users', + name: 'deleteSessions', + description: '/docs/references/users/delete-user-sessions.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -1979,12 +2206,19 @@ App::delete('/v1/users/:userId') ->label('scope', 'users.write') ->label('audits.event', 'user.delete') ->label('audits.resource', 'user/{request.userId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'delete') - ->label('sdk.description', '/docs/references/users/delete.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'users', + name: 'delete', + description: '/docs/references/users/delete.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('userId', '', new UID(), 'User ID.') ->inject('response') ->inject('dbForProject') @@ -2021,13 +2255,19 @@ App::delete('/v1/users/:userId/targets/:targetId') ->label('audits.resource', 'target/{request.$targetId}') ->label('event', 'users.[userId].targets.[targetId].delete') ->label('scope', 'targets.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'deleteTarget') - ->label('sdk.description', '/docs/references/users/delete-target.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'users', + name: 'deleteTarget', + description: '/docs/references/users/delete-target.md', + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('userId', '', new UID(), 'User ID.') ->param('targetId', '', new UID(), 'Target ID.') ->inject('queueForEvents') @@ -2072,12 +2312,19 @@ App::delete('/v1/users/identities/:identityId') ->label('scope', 'users.write') ->label('audits.event', 'identity.delete') ->label('audits.resource', 'identity/{request.$identityId}') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'deleteIdentity') - ->label('sdk.description', '/docs/references/users/delete-identity.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'users', + name: 'deleteIdentity', + description: '/docs/references/users/delete-identity.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE, + )) ->param('identityId', '', new UID(), 'Identity ID.') ->inject('response') ->inject('dbForProject') @@ -2104,13 +2351,18 @@ App::post('/v1/users/:userId/jwts') ->desc('Create user JWT') ->groups(['api', 'users']) ->label('scope', 'users.write') - ->label('sdk.auth', [APP_AUTH_TYPE_KEY]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'createJWT') - ->label('sdk.description', '/docs/references/users/create-user-jwt.md') - ->label('sdk.response.code', Response::STATUS_CODE_CREATED) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_JWT) + ->label('sdk', new Method( + namespace: 'users', + name: 'createJWT', + description: '/docs/references/users/create-user-jwt.md', + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_JWT, + ) + ] + )) ->param('userId', '', new UID(), 'User ID.') ->param('sessionId', '', new UID(), 'Session ID. Use the string \'recent\' to use the most recent session. Defaults to the most recent session.', true) ->param('duration', 900, new Range(0, 3600), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.', true) @@ -2154,12 +2406,18 @@ App::get('/v1/users/usage') ->desc('Get users usage stats') ->groups(['api', 'users']) ->label('scope', 'users.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'users') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_USERS) + ->label('sdk', new Method( + namespace: 'users', + name: 'getUsage', + description: '/docs/references/users/get-usage.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_USERS, + ) + ] + )) ->param('range', '30d', new WhiteList(['24h', '30d', '90d'], true), 'Date range.', true) ->inject('response') ->inject('dbForProject') diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index bbb1d9c3f8..29a186f9f2 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -4,16 +4,21 @@ use Appwrite\Auth\OAuth2\Github as OAuth2Github; use Appwrite\Event\Build; use Appwrite\Event\Delete; use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Database\Validator\Queries\Installations; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Appwrite\Vcs\Comment; use Utopia\App; -use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Exception\Duplicate; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; @@ -21,52 +26,66 @@ use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; -use Utopia\Detector\Adapter\Bun; -use Utopia\Detector\Adapter\CPP; -use Utopia\Detector\Adapter\Dart; -use Utopia\Detector\Adapter\Deno; -use Utopia\Detector\Adapter\Dotnet; -use Utopia\Detector\Adapter\Java; -use Utopia\Detector\Adapter\JavaScript; -use Utopia\Detector\Adapter\PHP; -use Utopia\Detector\Adapter\Python; -use Utopia\Detector\Adapter\Ruby; -use Utopia\Detector\Adapter\Swift; -use Utopia\Detector\Detector; +use Utopia\Detector\Detection\Framework\Astro; +use Utopia\Detector\Detection\Framework\Flutter; +use Utopia\Detector\Detection\Framework\NextJs; +use Utopia\Detector\Detection\Framework\Nuxt; +use Utopia\Detector\Detection\Framework\Remix; +use Utopia\Detector\Detection\Framework\SvelteKit; +use Utopia\Detector\Detection\Packager\NPM; +use Utopia\Detector\Detection\Packager\PNPM; +use Utopia\Detector\Detection\Packager\Yarn; +use Utopia\Detector\Detection\Runtime\Bun; +use Utopia\Detector\Detection\Runtime\CPP; +use Utopia\Detector\Detection\Runtime\Dart; +use Utopia\Detector\Detection\Runtime\Deno; +use Utopia\Detector\Detection\Runtime\Dotnet; +use Utopia\Detector\Detection\Runtime\Java; +use Utopia\Detector\Detection\Runtime\Node; +use Utopia\Detector\Detection\Runtime\PHP; +use Utopia\Detector\Detection\Runtime\Python; +use Utopia\Detector\Detection\Runtime\Ruby; +use Utopia\Detector\Detection\Runtime\Swift; +use Utopia\Detector\Detector\Framework; +use Utopia\Detector\Detector\Packager; +use Utopia\Detector\Detector\Runtime; +use Utopia\Detector\Detector\Strategy; use Utopia\System\System; use Utopia\Validator\Boolean; use Utopia\Validator\Host; use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; use Utopia\VCS\Adapter\Git\GitHub; use Utopia\VCS\Exception\RepositoryNotFound; use function Swoole\Coroutine\batch; -$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForConsole, Build $queueForBuilds, callable $getProjectDB, Request $request) { +$createGitDeployments = function (GitHub $github, string $providerInstallationId, array $repositories, string $providerBranch, string $providerBranchUrl, string $providerRepositoryName, string $providerRepositoryUrl, string $providerRepositoryOwner, string $providerCommitHash, string $providerCommitAuthor, string $providerCommitAuthorUrl, string $providerCommitMessage, string $providerCommitUrl, string $providerPullRequestId, bool $external, Database $dbForPlatform, Build $queueForBuilds, callable $getProjectDB, Request $request) { $errors = []; - foreach ($repositories as $resource) { + foreach ($repositories as $repository) { try { - $resourceType = $resource->getAttribute('resourceType'); + $resourceType = $repository->getAttribute('resourceType'); - if ($resourceType !== "function") { + if ($resourceType !== "function" && $resourceType !== "site") { continue; } - $projectId = $resource->getAttribute('projectId'); - $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); + $projectId = $repository->getAttribute('projectId'); + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); $dbForProject = $getProjectDB($project); - $functionId = $resource->getAttribute('resourceId'); - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $functionInternalId = $function->getInternalId(); + $resourceCollection = $resourceType === "function" ? 'functions' : 'sites'; + $resourceId = $repository->getAttribute('resourceId'); + $resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); + $resourceInternalId = $resource->getInternalId(); $deploymentId = ID::unique(); - $repositoryId = $resource->getId(); - $repositoryInternalId = $resource->getInternalId(); - $providerRepositoryId = $resource->getAttribute('providerRepositoryId'); - $installationId = $resource->getAttribute('installationId'); - $installationInternalId = $resource->getAttribute('installationInternalId'); - $productionBranch = $function->getAttribute('providerBranch'); + $repositoryId = $repository->getId(); + $repositoryInternalId = $repository->getInternalId(); + $providerRepositoryId = $repository->getAttribute('providerRepositoryId'); + $installationId = $repository->getAttribute('installationId'); + $installationInternalId = $repository->getAttribute('installationInternalId'); + $productionBranch = $resource->getAttribute('providerBranch'); $activate = false; if ($providerBranch == $productionBranch && $external === false) { @@ -90,7 +109,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $isAuthorized = !$external; if (!$isAuthorized && !empty($providerPullRequestId)) { - if (\in_array($providerPullRequestId, $resource->getAttribute('providerPullRequestIds', []))) { + if (\in_array($providerPullRequestId, $repository->getAttribute('providerPullRequestIds', []))) { $isAuthorized = true; } } @@ -103,8 +122,8 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = ''; - if (!empty($providerPullRequestId) && $function->getAttribute('providerSilentMode', false) === false) { - $latestComment = Authorization::skip(fn () => $dbForConsole->findOne('vcsComments', [ + if (!empty($providerPullRequestId) && $resource->getAttribute('providerSilentMode', false) === false) { + $latestComment = Authorization::skip(fn () => $dbForPlatform->findOne('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerPullRequestId', [$providerPullRequestId]), Query::orderDesc('$createdAt'), @@ -112,20 +131,21 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if (!$latestComment->isEmpty()) { $latestCommentId = $latestComment->getAttribute('providerCommentId', ''); + $comment = new Comment(); $comment->parseComment($github->getComment($owner, $repositoryName, $latestCommentId)); - $comment->addBuild($project, $function, $commentStatus, $deploymentId, $action); + $comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, ''); $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } else { $comment = new Comment(); - $comment->addBuild($project, $function, $commentStatus, $deploymentId, $action); + $comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, ''); $latestCommentId = \strval($github->createComment($owner, $repositoryName, $providerPullRequestId, $comment->generateComment())); if (!empty($latestCommentId)) { $teamId = $project->getAttribute('teamId', ''); - $latestComment = Authorization::skip(fn () => $dbForConsole->createDocument('vcsComments', new Document([ + $latestComment = Authorization::skip(fn () => $dbForPlatform->createDocument('vcsComments', new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::team(ID::custom($teamId))), @@ -146,7 +166,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } } } elseif (!empty($providerBranch)) { - $latestComments = Authorization::skip(fn () => $dbForConsole->find('vcsComments', [ + $latestComments = Authorization::skip(fn () => $dbForPlatform->find('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('providerBranch', [$providerBranch]), Query::orderDesc('$createdAt'), @@ -156,19 +176,19 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $latestCommentId = $comment->getAttribute('providerCommentId', ''); $comment = new Comment(); $comment->parseComment($github->getComment($owner, $repositoryName, $latestCommentId)); - $comment->addBuild($project, $function, $commentStatus, $deploymentId, $action); + $comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, ''); $latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment())); } } if (!$isAuthorized) { - $functionName = $function->getAttribute('name'); + $resourceName = $resource->getAttribute('name'); $projectName = $project->getAttribute('name'); - $name = "{$functionName} ({$projectName})"; + $name = "{$resourceName} ({$projectName})"; $message = 'Authorization required for external contributor.'; - $providerRepositoryId = $resource->getAttribute('providerRepositoryId'); + $providerRepositoryId = $repository->getAttribute('providerRepositoryId'); try { $repositoryName = $github->getRepositoryName($providerRepositoryId) ?? ''; if (empty($repositoryName)) { @@ -188,18 +208,32 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $providerRepositoryOwner = $pullRequestResponse['head']['repo']['name']; } - $deployment = $dbForProject->createDocument('deployments', new Document([ + $commands = []; + if (!empty($resource->getAttribute('installCommand', ''))) { + $commands[] = $resource->getAttribute('installCommand', ''); + } + if (!empty($resource->getAttribute('buildCommand', ''))) { + $commands[] = $resource->getAttribute('buildCommand', ''); + } + if (!empty($resource->getAttribute('commands', ''))) { + $commands[] = $resource->getAttribute('commands', ''); + } + + $deployment = Authorization::skip(fn () => $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, '$permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceId' => $functionId, - 'resourceInternalId' => $functionInternalId, - 'resourceType' => 'functions', - 'entrypoint' => $function->getAttribute('entrypoint'), - 'commands' => $function->getAttribute('commands'), + 'resourceId' => $resourceId, + 'resourceInternalId' => $resourceInternalId, + 'resourceType' => $resourceCollection, + 'entrypoint' => $resource->getAttribute('entrypoint', ''), + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $resource->getAttribute('outputDirectory', ''), + 'adapter' => $resource->getAttribute('adapter', ''), + 'fallbackFile' => $resource->getAttribute('fallbackFile', ''), 'type' => 'vcs', 'installationId' => $installationId, 'installationInternalId' => $installationInternalId, @@ -213,21 +247,120 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId 'providerCommitHash' => $providerCommitHash, 'providerCommitAuthorUrl' => $providerCommitAuthorUrl, 'providerCommitAuthor' => $providerCommitAuthor, - 'providerCommitMessage' => $providerCommitMessage, + 'providerCommitMessage' => mb_strimwidth($providerCommitMessage, 0, 255, '...'), 'providerCommitUrl' => $providerCommitUrl, 'providerCommentId' => \strval($latestCommentId), 'providerBranch' => $providerBranch, - 'search' => implode(' ', [$deploymentId, $function->getAttribute('entrypoint')]), + 'search' => implode(' ', [$deploymentId, $resource->getAttribute('entrypoint', '')]), 'activate' => $activate, - ])); + ]))); - if (!empty($providerCommitHash) && $function->getAttribute('providerSilentMode', false) === false) { - $functionName = $function->getAttribute('name'); + $resource = $resource + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); + + if ($resource->getCollection() === 'sites') { + $projectId = $project->getId(); + + // Deployment preview + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $domain = ID::unique() . "." . $sitesDomain; + $ruleId = md5($domain); + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + 'deploymentId' => $deployment->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentResourceType' => 'site', + 'deploymentResourceId' => $resourceId, + 'deploymentResourceInternalId' => $resourceInternalId, + 'deploymentVcsProviderBranch' => $providerBranch, + 'status' => 'verified', + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain]), + 'owner' => 'Appwrite', + 'region' => $project->getAttribute('region') + ])) + ); + + // VCS branch preview + if (!empty($providerBranch)) { + $domain = "branch-{$providerBranch}-{$resource->getId()}-{$project->getId()}.{$sitesDomain}"; + $ruleId = md5($domain); + try { + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + 'deploymentId' => $deployment->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentResourceType' => 'site', + 'deploymentResourceId' => $resourceId, + 'deploymentResourceInternalId' => $resourceInternalId, + 'deploymentVcsProviderBranch' => $providerBranch, + 'status' => 'verified', + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain]), + 'owner' => 'Appwrite', + 'region' => $project->getAttribute('region') + ])) + ); + } catch (Duplicate $err) { + // Ignore, rule already exists; will be updated by builds worker + } + } + + // VCS commit preview + if (!empty($providerCommitHash)) { + $domain = "commit-{$providerCommitHash}-{$resource->getId()}-{$project->getId()}.{$sitesDomain}"; + $ruleId = md5($domain); + try { + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + 'deploymentId' => $deployment->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentResourceType' => 'site', + 'deploymentResourceId' => $resourceId, + 'deploymentResourceInternalId' => $resourceInternalId, + 'deploymentVcsProviderBranch' => $providerBranch, + 'status' => 'verified', + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain]), + 'owner' => 'Appwrite', + 'region' => $project->getAttribute('region') + ])) + ); + } catch (Duplicate $err) { + // Ignore, rule already exists; will be updated by builds worker + } + } + } + + if (!empty($providerCommitHash) && $resource->getAttribute('providerSilentMode', false) === false) { + $resourceName = $resource->getAttribute('name'); $projectName = $project->getAttribute('name'); - $name = "{$functionName} ({$projectName})"; + $name = "{$resourceName} ({$projectName})"; $message = 'Starting...'; - $providerRepositoryId = $resource->getAttribute('providerRepositoryId'); + $providerRepositoryId = $repository->getAttribute('providerRepositoryId'); try { $repositoryName = $github->getRepositoryName($providerRepositoryId) ?? ''; if (empty($repositoryName)) { @@ -238,17 +371,17 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $owner = $github->getOwnerName($providerInstallationId); - $providerTargetUrl = $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$projectId/functions/function-$functionId"; + $providerTargetUrl = $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$projectId/$resourceCollection/$resourceType-$resourceId"; $github->updateCommitStatus($repositoryName, $providerCommitHash, $owner, 'pending', $message, $providerTargetUrl, $name); } $queueForBuilds ->setType(BUILD_TYPE_DEPLOYMENT) - ->setResource($function) + ->setResource($resource) ->setDeployment($deployment) ->setProject($project); // set the project because it won't be set for git deployments - $queueForBuilds->trigger(); // must trigger here so that we create a build for each function + $queueForBuilds->trigger(); // must trigger here so that we create a build for each function/site //TODO: Add event? } catch (Throwable $e) { @@ -267,15 +400,22 @@ App::get('/v1/vcs/github/authorize') ->desc('Install GitHub app') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') ->label('error', __DIR__ . '/../../views/general/error.phtml') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'createGitHubInstallation') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_MOVED_PERMANENTLY) - ->label('sdk.response.type', Response::CONTENT_TYPE_HTML) - ->label('sdk.methodType', 'webAuth') - ->label('sdk.hide', true) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'createGitHubInstallation', + description: '/docs/references/vcs/create-github-installation.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_MOVED_PERMANENTLY, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::HTML, + type: MethodType::WEBAUTH, + hide: true, + )) ->param('success', '', fn ($clients) => new Host($clients), 'URL to redirect back to console after a successful installation attempt.', true, ['clients']) ->param('failure', '', fn ($clients) => new Host($clients), 'URL to redirect back to console after a failed installation attempt.', true, ['clients']) ->inject('request') @@ -319,8 +459,8 @@ App::get('/v1/vcs/github/callback') ->inject('project') ->inject('request') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $providerInstallationId, string $setupAction, string $state, string $code, GitHub $github, Document $user, Document $project, Request $request, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $providerInstallationId, string $setupAction, string $state, string $code, GitHub $github, Document $user, Document $project, Request $request, Response $response, Database $dbForPlatform) { if (empty($state)) { $error = 'Installation requests from organisation members for the Appwrite GitHub App are currently unsupported. To proceed with the installation, login to the Appwrite Console and install the GitHub App.'; throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $error); @@ -339,7 +479,7 @@ App::get('/v1/vcs/github/callback') $redirectSuccess = $state['success'] ?? ''; $redirectFailure = $state['failure'] ?? ''; - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { $error = 'Project with the ID from state could not be found.'; @@ -355,53 +495,6 @@ App::get('/v1/vcs/github/callback') throw new Exception(Exception::PROJECT_NOT_FOUND, $error); } - $personalSlug = ''; - - // OAuth Authroization - if (!empty($code)) { - $oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), ""); - $accessToken = $oauth2->getAccessToken($code) ?? ''; - $refreshToken = $oauth2->getRefreshToken($code) ?? ''; - $accessTokenExpiry = $oauth2->getAccessTokenExpiry($code) ?? ''; - $personalSlug = $oauth2->getUserSlug($accessToken) ?? ''; - $email = $oauth2->getUserEmail($accessToken); - $oauth2ID = $oauth2->getUserID($accessToken); - - // Makes sure this email is not already used in another identity - $identity = $dbForConsole->findOne('identities', [ - Query::equal('providerEmail', [$email]), - ]); - if (!$identity->isEmpty()) { - if ($identity->getAttribute('userInternalId', '') !== $user->getInternalId()) { - throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); - } - - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry)); - - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); - } else { - $identity = $dbForConsole->createDocument('identities', new Document([ - '$id' => ID::unique(), - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::user($user->getId())), - Permission::delete(Role::user($user->getId())), - ], - 'userInternalId' => $user->getInternalId(), - 'userId' => $user->getId(), - 'provider' => 'github', - 'providerUid' => $oauth2ID, - 'providerEmail' => $email, - 'providerAccessToken' => $accessToken, - 'providerRefreshToken' => $refreshToken, - 'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry), - ])); - } - } - // Create / Update installation if (!empty($providerInstallationId)) { $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); @@ -411,11 +504,27 @@ App::get('/v1/vcs/github/callback') $projectInternalId = $project->getInternalId(); - $installation = $dbForConsole->findOne('installations', [ + $installation = $dbForPlatform->findOne('installations', [ Query::equal('providerInstallationId', [$providerInstallationId]), Query::equal('projectInternalId', [$projectInternalId]) ]); + $personal = false; + $refreshToken = null; + $accessToken = null; + $accessTokenExpiry = null; + + if (!empty($code)) { + $oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), ""); + + $accessToken = $oauth2->getAccessToken($code) ?? ''; + $refreshToken = $oauth2->getRefreshToken($code) ?? ''; + $accessTokenExpiry = DateTime::addSeconds(new \DateTime(), \intval($oauth2->getAccessTokenExpiry($code))); + + $personalSlug = $oauth2->getUserSlug($accessToken) ?? ''; + $personal = $personalSlug === $owner; + } + if ($installation->isEmpty()) { $teamId = $project->getAttribute('teamId', ''); @@ -433,15 +542,21 @@ App::get('/v1/vcs/github/callback') 'projectInternalId' => $projectInternalId, 'provider' => 'github', 'organization' => $owner, - 'personal' => $personalSlug === $owner + 'personal' => $personal, + 'personalRefreshToken' => $refreshToken, + 'personalAccessToken' => $accessToken, + 'personalAccessTokenExpiry' => $accessTokenExpiry, ]); - $installation = $dbForConsole->createDocument('installations', $installation); + $installation = $dbForPlatform->createDocument('installations', $installation); } else { $installation = $installation ->setAttribute('organization', $owner) - ->setAttribute('personal', $personalSlug === $owner); - $installation = $dbForConsole->updateDocument('installations', $installation->getId(), $installation); + ->setAttribute('personal', $personal) + ->setAttribute('personalRefreshToken', $refreshToken) + ->setAttribute('personalAccessToken', $accessToken) + ->setAttribute('personalAccessTokenExpiry', $accessTokenExpiry); + $installation = $dbForPlatform->updateDocument('installations', $installation->getId(), $installation); } } else { $error = 'Installation of the Appwrite GitHub App on organization accounts is restricted to organization owners. As a member of the organization, you do not have the necessary permissions to install this GitHub App. Please contact the organization owner to create the installation from the Appwrite console.'; @@ -467,22 +582,27 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->desc('Get files and directories of a VCS repository') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'getRepositoryContents') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_VCS_CONTENT_LIST) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'getRepositoryContents', + description: '/docs/references/vcs/get-repository-contents.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VCS_CONTENT_LIST, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('providerRepositoryId', '', new Text(256), 'Repository Id') ->param('providerRootDirectory', '', new Text(256, 0), 'Path to get contents of nested directory', true) ->inject('gitHub') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $providerRepositoryId, string $providerRootDirectory, GitHub $github, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, string $providerRepositoryId, string $providerRootDirectory, GitHub $github, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -524,26 +644,36 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ]), Response::MODEL_VCS_CONTENT_LIST); }); -App::post('/v1/vcs/github/installations/:installationId/providerRepositories/:providerRepositoryId/detection') - ->desc('Detect runtime settings from source code') +App::post('/v1/vcs/github/installations/:installationId/detections') + ->alias('/v1/vcs/github/installations/:installationId/providerRepositories/:providerRepositoryId/detection') + ->desc('Create repository detection') ->groups(['api', 'vcs']) ->label('scope', 'vcs.write') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'createRepositoryDetection') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_DETECTION) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'createRepositoryDetection', + description: '/docs/references/vcs/create-repository-detection.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DETECTION_RUNTIME, + ), + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DETECTION_FRAMEWORK, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('providerRepositoryId', '', new Text(256), 'Repository Id') + ->param('type', '', new WhiteList(['runtime', 'framework']), 'Detector type. Must be one of the following: runtime, framework') ->param('providerRootDirectory', '', new Text(256, 0), 'Path to Root Directory', true) ->inject('gitHub') ->inject('response') - ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $providerRepositoryId, string $providerRootDirectory, GitHub $github, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, string $providerRepositoryId, string $type, string $providerRootDirectory, GitHub $github, Response $response, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -568,57 +698,142 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories/:pr $files = \array_column($files, 'name'); $languages = $github->listRepositoryLanguages($owner, $repositoryName); - $detectorFactory = new Detector($files, $languages); + $detector = new Packager($files); + $detector + ->addOption(new Yarn()) + ->addOption(new PNPM()) + ->addOption(new NPM()); + $detection = $detector->detect(); - $detectorFactory - ->addDetector(new JavaScript()) - ->addDetector(new Bun()) - ->addDetector(new PHP()) - ->addDetector(new Python()) - ->addDetector(new Dart()) - ->addDetector(new Swift()) - ->addDetector(new Ruby()) - ->addDetector(new Java()) - ->addDetector(new CPP()) - ->addDetector(new Deno()) - ->addDetector(new Dotnet()); + $packager = !\is_null($detection) ? $detection->getName() : 'npm'; - $runtime = $detectorFactory->detect(); + if ($type === 'framework') { + $output = new Document([ + 'framework' => '', + 'installCommand' => '', + 'buildCommand' => '', + 'outputDirectory' => '', + ]); - $runtimes = Config::getParam('runtimes'); - $runtimeDetail = \array_reverse(\array_filter(\array_keys($runtimes), function ($key) use ($runtime, $runtimes) { - return $runtimes[$key]['key'] === $runtime; - }))[0] ?? ''; + $detector = new Framework($files, $packager); + $detector + ->addOption(new Flutter()) + ->addOption(new Nuxt()) + ->addOption(new Astro()) + ->addOption(new SvelteKit()) + ->addOption(new NextJs()) + ->addOption(new Remix()); - $detection = []; - $detection['runtime'] = $runtimeDetail; + $framework = $detector->detect(); - $response->dynamic(new Document($detection), Response::MODEL_DETECTION); + if (!\is_null($framework)) { + $output->setAttribute('installCommand', $framework->getInstallCommand()); + $output->setAttribute('buildCommand', $framework->getBuildCommand()); + $output->setAttribute('outputDirectory', $framework->getOutputDirectory()); + $framework = $framework->getName(); + } else { + $framework = 'other'; + $output->setAttribute('installCommand', ''); + $output->setAttribute('buildCommand', ''); + $output->setAttribute('outputDirectory', ''); + } + + $frameworks = Config::getParam('frameworks'); + if (!\in_array($framework, \array_keys($frameworks), true)) { + $framework = 'other'; + } + $output->setAttribute('framework', $framework); + } else { + $output = new Document([ + 'runtime' => '', + 'commands' => '', + 'entrypoint' => '', + ]); + + $strategies = [ + new Strategy(Strategy::FILEMATCH), + new Strategy(Strategy::LANGUAGES), + new Strategy(Strategy::EXTENSION), + ]; + + foreach ($strategies as $strategy) { + $detector = new Runtime($strategy === Strategy::LANGUAGES ? $languages : $files, $strategy, $packager); + $detector + ->addOption(new Node()) + ->addOption(new Bun()) + ->addOption(new Deno()) + ->addOption(new PHP()) + ->addOption(new Python()) + ->addOption(new Dart()) + ->addOption(new Swift()) + ->addOption(new Ruby()) + ->addOption(new Java()) + ->addOption(new CPP()) + ->addOption(new Dotnet()); + + $runtime = $detector->detect(); + + if (!\is_null($runtime)) { + $output->setAttribute('commands', $runtime->getCommands()); + $output->setAttribute('entrypoint', $runtime->getEntrypoint()); + $runtime = $runtime->getName(); + break; + } + } + + if (!empty($runtime)) { + $runtimes = Config::getParam('runtimes'); + $runtimeWithVersion = ''; + foreach ($runtimes as $runtimeKey => $runtimeConfig) { + if ($runtimeConfig['key'] === $runtime) { + $runtimeWithVersion = $runtimeKey; + } + } + + if (empty($runtimeWithVersion)) { + throw new Exception(Exception::FUNCTION_RUNTIME_NOT_DETECTED); + } + + $output->setAttribute('runtime', $runtimeWithVersion); + } else { + throw new Exception(Exception::FUNCTION_RUNTIME_NOT_DETECTED); + } + } + $response->dynamic($output, $type === 'framework' ? Response::MODEL_DETECTION_FRAMEWORK : Response::MODEL_DETECTION_RUNTIME); }); App::get('/v1/vcs/github/installations/:installationId/providerRepositories') ->desc('List repositories') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'listRepositories') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER_REPOSITORY_LIST) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'listRepositories', + description: '/docs/references/vcs/list-repositories.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST, + ), + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') + ->param('type', '', new WhiteList(['runtime', 'framework']), 'Detector type. Must be one of the following: runtime, framework') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('gitHub') ->inject('response') - ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $search, GitHub $github, Response $response, Document $project, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $installationId, string $type, string $search, GitHub $github, Response $response, Database $dbForPlatform) { if (empty($search)) { $search = ""; } - $installation = $dbForConsole->getDocument('installations', $installationId); + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -643,39 +858,86 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') return $repo; }, $repos); - $repos = batch(\array_map(function ($repo) use ($github) { - return function () use ($repo, $github) { - try { - $files = $github->listRepositoryContents($repo['organization'], $repo['name'], ''); - $files = \array_column($files, 'name'); + $repos = batch(\array_map(function ($repo) use ($type, $github) { + return function () use ($repo, $type, $github) { + $files = $github->listRepositoryContents($repo['organization'], $repo['name'], ''); + $files = \array_column($files, 'name'); + + $detector = new Packager($files); + $detector + ->addOption(new Yarn()) + ->addOption(new PNPM()) + ->addOption(new NPM()); + $detection = $detector->detect(); + + $packager = !\is_null($detection) ? $detection->getName() : 'npm'; + + if ($type === 'framework') { + $frameworkDetector = new Framework($files, $packager); + $frameworkDetector + ->addOption(new Flutter()) + ->addOption(new Nuxt()) + ->addOption(new Astro()) + ->addOption(new SvelteKit()) + ->addOption(new NextJs()) + ->addOption(new Remix()); + + $detectedFramework = $frameworkDetector->detect(); + + if (!\is_null($detectedFramework)) { + $framework = $detectedFramework->getName(); + } else { + $framework = 'other'; + } + + $frameworks = Config::getParam('frameworks'); + if (!\in_array($framework, \array_keys($frameworks), true)) { + $framework = 'other'; + } + $repo['framework'] = $framework; + } else { $languages = $github->listRepositoryLanguages($repo['organization'], $repo['name']); - $detectorFactory = new Detector($files, $languages); + $strategies = [ + new Strategy(Strategy::FILEMATCH), + new Strategy(Strategy::LANGUAGES), + new Strategy(Strategy::EXTENSION), + ]; - $detectorFactory - ->addDetector(new JavaScript()) - ->addDetector(new Bun()) - ->addDetector(new PHP()) - ->addDetector(new Python()) - ->addDetector(new Dart()) - ->addDetector(new Swift()) - ->addDetector(new Ruby()) - ->addDetector(new Java()) - ->addDetector(new CPP()) - ->addDetector(new Deno()) - ->addDetector(new Dotnet()); + foreach ($strategies as $strategy) { + $detector = new Runtime($strategy === Strategy::LANGUAGES ? $languages : $files, $strategy, $packager); + $detector + ->addOption(new Node()) + ->addOption(new Bun()) + ->addOption(new Deno()) + ->addOption(new PHP()) + ->addOption(new Python()) + ->addOption(new Dart()) + ->addOption(new Swift()) + ->addOption(new Ruby()) + ->addOption(new Java()) + ->addOption(new CPP()) + ->addOption(new Dotnet()); - $runtime = $detectorFactory->detect(); + $runtime = $detector->detect(); - $runtimes = Config::getParam('runtimes'); - $runtimeDetail = \array_reverse(\array_filter(\array_keys($runtimes), function ($key) use ($runtime, $runtimes) { - return $runtimes[$key]['key'] === $runtime; - }))[0] ?? ''; + if (!\is_null($runtime)) { + $runtime = $runtime->getName(); + break; + } + } - $repo['runtime'] = $runtimeDetail; - } catch (Throwable $error) { - $repo['runtime'] = ""; - Console::warning("Runtime not detected for " . $repo['organization'] . "/" . $repo['name']); + if (!empty($runtime)) { + $runtimes = Config::getParam('runtimes'); + $runtimeWithVersion = ''; + foreach ($runtimes as $runtimeKey => $runtimeConfig) { + if ($runtimeConfig['key'] === $runtime) { + $runtimeWithVersion = $runtimeKey; + } + } + + $repo['runtime'] = $runtimeWithVersion ?? ''; + } } return $repo; }; @@ -686,22 +948,27 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories') }, $repos); $response->dynamic(new Document([ - 'providerRepositories' => $repos, + $type === 'framework' ? 'frameworkProviderRepositories' : 'runtimeProviderRepositories' => $repos, 'total' => \count($repos), - ]), Response::MODEL_PROVIDER_REPOSITORY_LIST); + ]), ($type === 'framework') ? Response::MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST : Response::MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST); }); App::post('/v1/vcs/github/installations/:installationId/providerRepositories') ->desc('Create repository') ->groups(['api', 'vcs']) ->label('scope', 'vcs.write') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'createRepository') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER_REPOSITORY) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'createRepository', + description: '/docs/references/vcs/create-repository.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER_REPOSITORY, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('name', '', new Text(256), 'Repository name (slug)') ->param('private', '', new Boolean(false), 'Mark repository public or private') @@ -709,9 +976,9 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') ->inject('user') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $name, bool $private, GitHub $github, Document $user, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, string $name, bool $private, GitHub $github, Document $user, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -720,17 +987,23 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') if ($installation->getAttribute('personal', false) === true) { $oauth2 = new OAuth2Github(System::getEnv('_APP_VCS_GITHUB_CLIENT_ID', ''), System::getEnv('_APP_VCS_GITHUB_CLIENT_SECRET', ''), ""); - $identity = $dbForConsole->findOne('identities', [ - Query::equal('provider', ['github']), - Query::equal('userInternalId', [$user->getInternalId()]), - ]); - if ($identity->isEmpty()) { - throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); - } + $accessToken = $installation->getAttribute('personalAccessToken'); + $refreshToken = $installation->getAttribute('personalRefreshToken'); + $accessTokenExpiry = $installation->getAttribute('personalAccessTokenExpiry'); - $accessToken = $identity->getAttribute('providerAccessToken'); - $refreshToken = $identity->getAttribute('providerRefreshToken'); - $accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry'); + if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) { + $identity = $dbForPlatform->findOne('identities', [ + Query::equal('provider', ['github']), + Query::equal('userInternalId', [$user->getInternalId()]), + ]); + if ($identity->isEmpty()) { + throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); + } + + $accessToken = $accessToken ?? $identity->getAttribute('providerAccessToken'); + $refreshToken = $refreshToken ?? $identity->getAttribute('providerRefreshToken'); + $accessTokenExpiry = $accessTokenExpiry ?? $identity->getAttribute('providerAccessTokenExpiry'); + } $isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now'); if ($isExpired) { @@ -745,12 +1018,12 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, "Another request is currently refreshing OAuth token. Please try again."); } - $identity = $identity - ->setAttribute('providerAccessToken', $accessToken) - ->setAttribute('providerRefreshToken', $refreshToken) - ->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); + $installation = $installation + ->setAttribute('personalAccessToken', $accessToken) + ->setAttribute('personalRefreshToken', $refreshToken) + ->setAttribute('personalAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$oauth2->getAccessTokenExpiry(''))); - $dbForConsole->updateDocument('identities', $identity->getId(), $identity); + $dbForPlatform->updateDocument('installations', $installation->getId(), $installation); } try { @@ -796,21 +1069,26 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->desc('Get repository') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'getRepository') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_PROVIDER_REPOSITORY) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'getRepository', + description: '/docs/references/vcs/get-repository.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_PROVIDER_REPOSITORY, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('providerRepositoryId', '', new Text(256), 'Repository Id') ->inject('gitHub') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $providerRepositoryId, GitHub $github, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, string $providerRepositoryId, GitHub $github, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -845,21 +1123,26 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:pro ->desc('List repository branches') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'listRepositoryBranches') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BRANCH_LIST) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'listRepositoryBranches', + description: '/docs/references/vcs/list-repository-branches.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_BRANCH_LIST, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('providerRepositoryId', '', new Text(256), 'Repository Id') ->inject('gitHub') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, string $providerRepositoryId, GitHub $github, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, string $providerRepositoryId, GitHub $github, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -897,11 +1180,11 @@ App::post('/v1/vcs/github/events') ->inject('gitHub') ->inject('request') ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForBuilds') ->action( - function (GitHub $github, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { + function (GitHub $github, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { $payload = $request->getRawPayload(); $signatureRemote = $request->getHeader('x-hub-signature-256', ''); $signatureLocal = System::getEnv('_APP_VCS_GITHUB_WEBHOOK_SECRET', ''); @@ -934,37 +1217,37 @@ App::post('/v1/vcs/github/events') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); - //find functionId from functions table - $repositories = Authorization::skip(fn () => $dbForConsole->find('repositories', [ + //find resourceId from relevant resources table + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::limit(100), ])); // create new deployment only on push and not when branch is created if (!$providerBranchCreated) { - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForConsole, $queueForBuilds, $getProjectDB, $request); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); } } elseif ($event == $github::EVENT_INSTALLATION) { if ($parsedPayload["action"] == "deleted") { - // TODO: Use worker for this job instead (update function as well) + // TODO: Use worker for this job instead (update function/site as well) $providerInstallationId = $parsedPayload["installationId"]; - $installations = $dbForConsole->find('installations', [ + $installations = $dbForPlatform->find('installations', [ Query::equal('providerInstallationId', [$providerInstallationId]), Query::limit(1000) ]); foreach ($installations as $installation) { - $repositories = Authorization::skip(fn () => $dbForConsole->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('installationInternalId', [$installation->getInternalId()]), Query::limit(1000) ])); foreach ($repositories as $repository) { - Authorization::skip(fn () => $dbForConsole->deleteDocument('repositories', $repository->getId())); + Authorization::skip(fn () => $dbForPlatform->deleteDocument('repositories', $repository->getId())); } - $dbForConsole->deleteDocument('installations', $installation->getId()); + $dbForPlatform->deleteDocument('installations', $installation->getId()); } } } elseif ($event == $github::EVENT_PULL_REQUEST) { @@ -993,12 +1276,12 @@ App::post('/v1/vcs/github/events') $providerCommitAuthor = $commitDetails["commitAuthor"] ?? ''; $providerCommitMessage = $commitDetails["commitMessage"] ?? ''; - $repositories = Authorization::skip(fn () => $dbForConsole->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForConsole, $queueForBuilds, $getProjectDB, $request); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, $providerPullRequestId, $external, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); } elseif ($parsedPayload["action"] == "closed") { // Allowed external contributions cleanup @@ -1007,7 +1290,7 @@ App::post('/v1/vcs/github/events') $external = $parsedPayload["external"] ?? true; if ($external) { - $repositories = Authorization::skip(fn () => $dbForConsole->find('repositories', [ + $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::orderDesc('$createdAt') ])); @@ -1018,7 +1301,7 @@ App::post('/v1/vcs/github/events') if (\in_array($providerPullRequestId, $providerPullRequestIds)) { $providerPullRequestIds = \array_diff($providerPullRequestIds, [$providerPullRequestId]); $repository = $repository->setAttribute('providerPullRequestIds', $providerPullRequestIds); - $repository = Authorization::skip(fn () => $dbForConsole->updateDocument('repositories', $repository->getId(), $repository)); + $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); } } } @@ -1033,20 +1316,25 @@ App::get('/v1/vcs/installations') ->desc('List installations') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'listInstallations') - ->label('sdk.description', '/docs/references/vcs/list-installations.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_INSTALLATION_LIST) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'listInstallations', + description: '/docs/references/vcs/list-installations.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_INSTALLATION_LIST, + ) + ] + )) ->param('queries', [], new Installations(), '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(', ', Installations::ALLOWED_ATTRIBUTES), true) ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->inject('response') ->inject('project') ->inject('dbForProject') - ->inject('dbForConsole') - ->action(function (array $queries, string $search, Response $response, Document $project, Database $dbForProject, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (array $queries, string $search, Response $response, Document $project, Database $dbForProject, Database $dbForPlatform) { try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { @@ -1075,7 +1363,7 @@ App::get('/v1/vcs/installations') } $installationId = $cursor->getValue(); - $cursorDocument = $dbForConsole->getDocument('installations', $installationId); + $cursorDocument = $dbForPlatform->getDocument('installations', $installationId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Installation '{$installationId}' for the 'cursor' value not found."); @@ -1086,8 +1374,8 @@ App::get('/v1/vcs/installations') $filterQueries = Query::groupByType($queries)['filters']; - $results = $dbForConsole->find('installations', $queries); - $total = $dbForConsole->count('installations', $filterQueries, APP_LIMIT_COUNT); + $results = $dbForPlatform->find('installations', $queries); + $total = $dbForPlatform->count('installations', $filterQueries, APP_LIMIT_COUNT); $response->dynamic(new Document([ 'installations' => $results, @@ -1099,19 +1387,24 @@ App::get('/v1/vcs/installations/:installationId') ->desc('Get installation') ->groups(['api', 'vcs']) ->label('scope', 'vcs.read') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'getInstallation') - ->label('sdk.description', '/docs/references/vcs/get-installation.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_INSTALLATION) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'getInstallation', + description: '/docs/references/vcs/get-installation.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_INSTALLATION, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->inject('response') ->inject('project') - ->inject('dbForConsole') - ->action(function (string $installationId, Response $response, Document $project, Database $dbForConsole) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->inject('dbForPlatform') + ->action(function (string $installationId, Response $response, Document $project, Database $dbForPlatform) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation === false || $installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); @@ -1128,25 +1421,32 @@ App::delete('/v1/vcs/installations/:installationId') ->desc('Delete installation') ->groups(['api', 'vcs']) ->label('scope', 'vcs.write') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'deleteInstallation') - ->label('sdk.description', '/docs/references/vcs/delete-installation.md') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'deleteInstallation', + description: '/docs/references/vcs/delete-installation.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) ->param('installationId', '', new Text(256), 'Installation Id') ->inject('response') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForDeletes') - ->action(function (string $installationId, Response $response, Document $project, Database $dbForConsole, Delete $queueForDeletes) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->action(function (string $installationId, Response $response, Document $project, Database $dbForPlatform, Delete $queueForDeletes) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - if (!$dbForConsole->deleteDocument('installations', $installation->getId())) { + if (!$dbForPlatform->deleteDocument('installations', $installation->getId())) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove installation from DB'); } @@ -1161,12 +1461,18 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->desc('Authorize external deployment') ->groups(['api', 'vcs']) ->label('scope', 'vcs.write') - ->label('sdk.namespace', 'vcs') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.method', 'updateExternalDeployments') - ->label('sdk.description', '') - ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT) - ->label('sdk.response.model', Response::MODEL_NONE) + ->label('sdk', new Method( + namespace: 'vcs', + name: 'updateExternalDeployments', + description: '/docs/references/vcs/update-external-deployments.md', + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ] + )) ->param('installationId', '', new Text(256), 'Installation Id') ->param('repositoryId', '', new Text(256), 'VCS Repository Id') ->param('providerPullRequestId', '', new Text(256), 'GitHub Pull Request Id') @@ -1174,17 +1480,17 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor ->inject('request') ->inject('response') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForBuilds') - ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForConsole, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { - $installation = $dbForConsole->getDocument('installations', $installationId); + ->action(function (string $installationId, string $repositoryId, string $providerPullRequestId, GitHub $github, Request $request, Response $response, Document $project, Database $dbForPlatform, callable $getProjectDB, Build $queueForBuilds) use ($createGitDeployments) { + $installation = $dbForPlatform->getDocument('installations', $installationId); if ($installation->isEmpty()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - $repository = Authorization::skip(fn () => $dbForConsole->getDocument('repositories', $repositoryId, [ + $repository = Authorization::skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ Query::equal('projectInternalId', [$project->getInternalId()]) ])); @@ -1201,7 +1507,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor // TODO: Delete from array when PR is closed - $repository = Authorization::skip(fn () => $dbForConsole->updateDocument('repositories', $repository->getId(), $repository)); + $repository = Authorization::skip(fn () => $dbForPlatform->updateDocument('repositories', $repository->getId(), $repository)); $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); @@ -1225,7 +1531,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor $providerBranch = \explode(':', $pullRequestResponse['head']['label'])[1] ?? ''; $providerCommitHash = $pullRequestResponse['head']['sha'] ?? ''; - $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerCommitHash, $providerPullRequestId, true, $dbForConsole, $queueForBuilds, $getProjectDB, $request); + $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerCommitHash, $providerPullRequestId, true, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); $response->noContent(); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index 663242882a..8985c82db6 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -3,21 +3,30 @@ require_once __DIR__ . '/../init.php'; use Ahc\Jwt\JWT; +use Ahc\Jwt\JWTException; use Appwrite\Auth\Auth; +use Appwrite\Auth\Key; use Appwrite\Event\Certificate; use Appwrite\Event\Event; use Appwrite\Event\Func; -use Appwrite\Event\Usage; +use Appwrite\Event\StatsUsage; use Appwrite\Extend\Exception as AppwriteException; use Appwrite\Network\Validator\Origin; +use Appwrite\Platform\Appwrite; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Transformation\Adapter\Preview; +use Appwrite\Transformation\Transformation; use Appwrite\Utopia\Request; use Appwrite\Utopia\Request\Filters\V16 as RequestV16; use Appwrite\Utopia\Request\Filters\V17 as RequestV17; use Appwrite\Utopia\Request\Filters\V18 as RequestV18; +use Appwrite\Utopia\Request\Filters\V19 as RequestV19; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Filters\V16 as ResponseV16; use Appwrite\Utopia\Response\Filters\V17 as ResponseV17; use Appwrite\Utopia\Response\Filters\V18 as ResponseV18; +use Appwrite\Utopia\Response\Filters\V19 as ResponseV19; use Appwrite\Utopia\View; use Executor\Executor; use MaxMind\Db\Reader; @@ -29,6 +38,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Domains\Domain; use Utopia\DSN\DSN; @@ -37,6 +47,7 @@ use Utopia\Logger\Adapter\Sentry; use Utopia\Logger\Log; use Utopia\Logger\Log\User; use Utopia\Logger\Logger; +use Utopia\Platform\Service; use Utopia\System\System; use Utopia\Validator\Hostname; use Utopia\Validator\Text; @@ -45,42 +56,67 @@ Config::setParam('domainVerification', false); Config::setParam('cookieDomain', 'localhost'); Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE); -function router(App $utopia, Database $dbForConsole, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked) +function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { - $utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml'); - $host = $request->getHostname() ?? ''; + if (!empty($previewHostname)) { + $host = $previewHostname; + } - $route = Authorization::skip(fn () => $dbForConsole->getDocument('rules', md5($host))); + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { + $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($host))); + } else { + $rule = Authorization::skip( + fn () => $dbForPlatform->find('rules', [ + Query::equal('domain', [$host]), + Query::limit(1) + ]) + )[0] ?? new Document(); + } - if ($route->isEmpty()) { - if ($host === System::getEnv('_APP_DOMAIN_FUNCTIONS', '')) { - throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.'); + $errorView = __DIR__ . '/../views/general/error.phtml'; + $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . '://' . System::getEnv('_APP_DOMAIN', ''); + + if ($rule->isEmpty()) { + if ($host === System::getEnv('_APP_DOMAIN_FUNCTIONS', '') || $host === System::getEnv('_APP_DOMAIN_SITES', '')) { + throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain cannot be used for security reasons. Please use any subdomain instead.', view: $errorView); } - if (\str_ends_with($host, System::getEnv('_APP_DOMAIN_FUNCTIONS', ''))) { - throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'This domain is not connected to any Appwrite resource yet. Please configure custom domain or function domain to allow this request.'); + if (\str_ends_with($host, System::getEnv('_APP_DOMAIN_FUNCTIONS', '')) || \str_ends_with($host, System::getEnv('_APP_DOMAIN_SITES', ''))) { + $exception = new AppwriteException(AppwriteException::RULE_NOT_FOUND, 'This domain is not connected to any Appwrite resources. Visit domains tab under function/site settings to configure it.', view: $errorView); + + $exception->addCTA('Start with this domain', $url . '/console'); + throw $exception; } if (System::getEnv('_APP_OPTIONS_ROUTER_PROTECTION', 'disabled') === 'enabled') { - if ($host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL) { // localhost allowed for proxy, APP_HOSTNAME_INTERNAL allowed for migrations - throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'Router protection does not allow accessing Appwrite over this domain. Please add it as custom domain to your project or disable _APP_OPTIONS_ROUTER_PROTECTION environment variable.'); + if ($host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL && $host !== System::getEnv('_APP_CONSOLE_DOMAIN', '')) { + throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'Router protection does not allow accessing Appwrite over this domain. Please add it as custom domain to your project or disable _APP_OPTIONS_ROUTER_PROTECTION environment variable.', view: $errorView); } } // Act as API - no Proxy logic - $utopia->getRoute()?->label('error', ''); return false; } - $projectId = $route->getAttribute('projectId'); + $projectId = $rule->getAttribute('projectId'); $project = Authorization::skip( - fn () => $dbForConsole->getDocument('projects', $projectId) + fn () => $dbForPlatform->getDocument('projects', $projectId) ); + + if (!$project->isEmpty() && $project->getId() !== 'console') { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + } + } + if (array_key_exists('proxy', $project->getAttribute('services', []))) { $status = $project->getAttribute('services', [])['proxy']; if (!$status) { - throw new AppwriteException(AppwriteException::GENERAL_SERVICE_DISABLED); + throw new AppwriteException(AppwriteException::GENERAL_SERVICE_DISABLED, view: $errorView); } } @@ -90,24 +126,44 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo return false; } - $type = $route->getAttribute('resourceType'); + $type = $rule->getAttribute('type', ''); - if ($type === 'function') { - $utopia->getRoute()?->label('sdk.namespace', 'functions'); - $utopia->getRoute()?->label('sdk.method', 'createExecution'); - - if (System::getEnv('_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS - if ($request->getProtocol() !== 'https') { + if ($type === 'deployment') { + if (System::getEnv('_APP_OPTIONS_ROUTER_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS + if ($request->getProtocol() !== 'https' && $request->getHostname() !== APP_HOSTNAME_INTERNAL) { if ($request->getMethod() !== Request::METHOD_GET) { - throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP. Please use HTTPS instead.'); + throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP. Please use HTTPS instead.', view: $errorView); } - return $response->redirect('https://' . $request->getHostname() . $request->getURI()); } } - $functionId = $route->getAttribute('resourceId'); - $projectId = $route->getAttribute('projectId'); + /** @var Database $dbForProject */ + $dbForProject = $getProjectDB($project); + + /** @var Document $deployment */ + $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $rule->getAttribute('deploymentId'))); + + if ($deployment->getAttribute('resourceType', '') === 'functions') { + $type = 'function'; + } elseif ($deployment->getAttribute('resourceType', '') === 'sites') { + $type = 'site'; + } + + if ($deployment->isEmpty()) { + $resourceType = $rule->getAttribute('deploymentResourceType', ''); + $resourceId = $rule->getAttribute('deploymentResourceId', ''); + $type = ($resourceType === 'site') ? 'sites' : 'functions'; + $exception = new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, view: $errorView); + $exception->addCTA('View deployments', $url . '/console/project-' . $projectId . '/' . $type . '/' . $resourceType . '-' . $resourceId); + throw $exception; + } + + $resource = $type === 'function' ? + Authorization::skip(fn () => $dbForProject->getDocument('functions', $deployment->getAttribute('resourceId', ''))) : + Authorization::skip(fn () => $dbForProject->getDocument('sites', $deployment->getAttribute('resourceId', ''))); + + $isPreview = $type === 'function' ? false : ($rule->getAttribute('trigger', '') !== 'manual'); $path = ($swooleRequest->server['request_uri'] ?? '/'); $query = ($swooleRequest->server['query_string'] ?? ''); @@ -115,78 +171,170 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $path .= '?' . $query; } + $protocol = $request->getProtocol(); + + /** + Ensure preview authorization + - Authorization is skippable for tests, and build screenshot + - If cookie is not sent by client -> not authorized + - If JWT in cookie is invalid or expired -> not authorized + - If user is blocked or removed -> not authorized + - If user's session is removed or expired -> not authorized + - If user is not member of team of this deployment -> not authorized + - If not authorized, redirect to Console redirect UI + - If authorized, continue as if auth was not required + */ + $requirePreview = \is_null($apiKey) || !$apiKey->isPreviewAuthDisabled(); + if ($isPreview && $requirePreview) { + $cookie = $request->getCookie(Auth::$cookieNamePreview, ''); + $authorized = false; + + // Security checks to mark authorized true + if (!empty($cookie)) { + $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); + + $payload = []; + try { + $payload = $jwt->decode($cookie); + } catch (JWTException $error) { + // Authorized remains false + } + + $userExists = false; + $userId = $payload['userId'] ?? ''; + if (!empty($userId)) { + $user = Authorization::skip(fn () => $dbForPlatform->getDocument('users', $userId)); + if (!$user->isEmpty() && $user->getAttribute('status', false)) { + $userExists = true; + } + } + + $sessionExists = false; + $jwtSessionId = $payload['sessionId'] ?? ''; + if (!empty($jwtSessionId) && !empty($user->find('$id', $jwtSessionId, 'sessions'))) { + $sessionExists = true; + } + + $membershipExists = false; + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + if (!$project->isEmpty() && isset($user)) { + $teamId = $project->getAttribute('teamId', ''); + $membership = $user->find('teamId', $teamId, 'memberships'); + if (!empty($membership)) { + $membershipExists = true; + } + } + + if ($userExists && $sessionExists && $membershipExists) { + $authorized = true; + } + } + + if (!$authorized) { + $url = (System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https') . "://" . System::getEnv('_APP_DOMAIN'); + $response + ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') + ->addHeader('Pragma', 'no-cache') + ->redirect($url . '/console/auth/preview?' + . \http_build_query([ + 'projectId' => $projectId, + 'origin' => $protocol . '://' . $host, + 'path' => $path + ])); + return true; + } + } $body = $swooleRequest->getContent() ?? ''; $method = $swooleRequest->server['request_method']; $requestHeaders = $request->getHeaders(); - $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); - - $dbForProject = $getProjectDB($project); - - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - - if ($function->isEmpty() || !$function->getAttribute('enabled')) { - throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND); + if ($resource->isEmpty() || !$resource->getAttribute('enabled')) { + if ($type === 'functions') { + throw new AppwriteException(AppwriteException::FUNCTION_NOT_FOUND, view: $errorView); + } else { + throw new AppwriteException(AppwriteException::SITE_NOT_FOUND, view: $errorView); + } } - if ($isResourceBlocked($project, RESOURCE_TYPE_FUNCTIONS, $functionId)) { - throw new AppwriteException(AppwriteException::GENERAL_RESOURCE_BLOCKED); + if ($isResourceBlocked($project, $type === 'function' ? RESOURCE_TYPE_FUNCTIONS : RESOURCE_TYPE_SITES, $resource->getId())) { + throw new AppwriteException(AppwriteException::GENERAL_RESOURCE_BLOCKED, view: $errorView); } - $version = $function->getAttribute('version', 'v2'); + $version = match ($type) { + 'function' => $resource->getAttribute('version', 'v2'), + 'site' => 'v5', + }; + $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); - $spec = Config::getParam('runtime-specifications')[$function->getAttribute('specification', APP_FUNCTION_SPECIFICATION_DEFAULT)]; + $spec = Config::getParam('specifications')[$resource->getAttribute('specification', APP_COMPUTE_SPECIFICATION_DEFAULT)]; - $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null; + $runtime = match ($type) { + 'function' => $runtimes[$resource->getAttribute('runtime')] ?? null, + 'site' => $runtimes[$resource->getAttribute('buildRuntime')] ?? null, + default => null + }; + + // Static site enforced runtime + if ($deployment->getAttribute('adapter', '') === 'static') { + $runtime = $runtimes['static-1'] ?? null; + } if (\is_null($runtime)) { - throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); + throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported', view: $errorView); } - $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', ''))); + $allowAnyStatus = !\is_null($apiKey) && $apiKey->isDeploymentStatusIgnored(); + if (!$allowAnyStatus && $deployment->getAttribute('status') !== 'ready') { + $status = $deployment->getAttribute('status'); - if ($deployment->getAttribute('resourceId') !== $function->getId()) { - throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); + switch ($status) { + case 'failed': + $exception = new AppwriteException(AppwriteException::BUILD_FAILED, view: $errorView); + $ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments/deployment-' . $deployment->getId(); + $exception->addCTA('View logs', $url . $ctaUrl); + break; + case 'canceled': + $exception = new AppwriteException(AppwriteException::BUILD_CANCELED, view: $errorView); + $ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments'; + $exception->addCTA('View deployments', $url . $ctaUrl); + break; + default: + $exception = new AppwriteException(AppwriteException::BUILD_NOT_READY, view: $errorView); + $ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments/deployment-' . $deployment->getId(); + $exception->addCTA('Reload', '/'); + $exception->addCTA('View logs', $url . $ctaUrl); + break; + } + throw $exception; } - if ($deployment->isEmpty()) { - throw new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); + if ($type === 'function') { + $permissions = $resource->getAttribute('execute'); + if (!(\in_array('any', $permissions)) && !(\in_array('guests', $permissions))) { + $exception = new AppwriteException(AppwriteException::FUNCTION_EXECUTE_PERMISSION_MISSING, view: $errorView); + $exception->addCTA('View settings', $url . '/console/project-' . $project->getId() . '/functions/function-' . $resource->getId() . '/settings'); + throw $exception; + } } - /** Check if build has completed */ - $build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''))); - if ($build->isEmpty()) { - throw new AppwriteException(AppwriteException::BUILD_NOT_FOUND); - } - - if ($build->getAttribute('status') !== 'ready') { - throw new AppwriteException(AppwriteException::BUILD_NOT_READY); - } - - $permissions = $function->getAttribute('execute'); - - if (!(\in_array('any', $permissions)) && !(\in_array('guests', $permissions))) { - throw new AppwriteException(AppwriteException::USER_UNAUTHORIZED, 'To execute function using domain, execute permissions must include "any" or "guests"'); - } - - $jwtExpiry = $function->getAttribute('timeout', 900); - $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $jwtExpiry, 0); - $apiKey = $jwtObj->encode([ - 'projectId' => $project->getId(), - 'scopes' => $function->getAttribute('scopes', []) - ]); - $headers = \array_merge([], $requestHeaders); - $headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $apiKey; - $headers['x-appwrite-trigger'] = 'http'; $headers['x-appwrite-user-id'] = ''; - $headers['x-appwrite-user-jwt'] = ''; $headers['x-appwrite-country-code'] = ''; $headers['x-appwrite-continent-code'] = ''; $headers['x-appwrite-continent-eu'] = 'false'; + $jwtExpiry = $resource->getAttribute('timeout', 900); + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $jwtExpiry, 0); + $jwtKey = $jwtObj->encode([ + 'projectId' => $project->getId(), + 'scopes' => $resource->getAttribute('scopes', []) + ]); + $headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $jwtKey; + $headers['x-appwrite-trigger'] = 'http'; + $headers['x-appwrite-user-jwt'] = ''; + $ip = $headers['x-real-ip'] ?? ''; if (!empty($ip)) { $record = $geodb->get($ip); @@ -212,12 +360,10 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $execution = new Document([ '$id' => $executionId, '$permissions' => [], - 'functionInternalId' => $function->getInternalId(), - 'functionId' => $function->getId(), + 'resourceInternalId' => $resource->getInternalId(), + 'resourceId' => $resource->getId(), 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentId' => $deployment->getId(), - 'trigger' => 'http', // http / schedule / event - 'status' => 'processing', // waiting / processing / completed / failed 'responseStatusCode' => 0, 'responseHeaders' => [], 'requestPath' => $path, @@ -226,13 +372,25 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo 'errors' => '', 'logs' => '', 'duration' => 0.0, - 'search' => implode(' ', [$functionId, $executionId]), ]); - $queueForEvents - ->setParam('functionId', $function->getId()) - ->setParam('executionId', $execution->getId()) - ->setContext('function', $function); + if ($type === 'function') { + $execution->setAttribute('resourceType', 'functions'); + $execution->setAttribute('trigger', 'http'); // http / schedule / event + $execution->setAttribute('status', 'processing'); // waiting / processing / completed / failed + + $queueForEvents + ->setParam('functionId', $resource->getId()) + ->setParam('executionId', $execution->getId()) + ->setContext('function', $resource); + } elseif ($type === 'site') { + $execution->setAttribute('resourceType', 'sites'); + + $queueForEvents + ->setParam('siteId', $resource->getId()) + ->setParam('executionId', $execution->getId()) + ->setContext('site', $resource); + } $durationStart = \microtime(true); @@ -249,12 +407,12 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo } // Shared vars - foreach ($function->getAttribute('varsProject', []) as $var) { + foreach ($resource->getAttribute('varsProject', []) as $var) { $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); } // Function vars - foreach ($function->getAttribute('vars', []) as $var) { + foreach ($resource->getAttribute('vars', []) as $var) { $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); } @@ -265,14 +423,14 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo // Appwrite vars $vars = \array_merge($vars, [ 'APPWRITE_FUNCTION_API_ENDPOINT' => $endpoint, - 'APPWRITE_FUNCTION_ID' => $functionId, - 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name'), + 'APPWRITE_FUNCTION_ID' => $resource->getId(), + 'APPWRITE_FUNCTION_NAME' => $resource->getAttribute('name'), 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', - 'APPWRITE_FUNCTION_CPUS' => $spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT, - 'APPWRITE_FUNCTION_MEMORY' => $spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT, + 'APPWRITE_FUNCTION_CPUS' => $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT, + 'APPWRITE_FUNCTION_MEMORY' => $spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT, 'APPWRITE_VERSION' => APP_VERSION_STABLE, 'APPWRITE_REGION' => $project->getAttribute('region'), 'APPWRITE_DEPLOYMENT_TYPE' => $deployment->getAttribute('type', ''), @@ -290,32 +448,114 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo 'APPWRITE_VCS_ROOT_DIRECTORY' => $deployment->getAttribute('providerRootDirectory', ''), ]); + // SPA fallbackFile override + if ($deployment->getAttribute('adapter', '') === 'static' && $deployment->getAttribute('fallbackFile', '') !== '') { + $vars['OPEN_RUNTIMES_STATIC_FALLBACK'] = $deployment->getAttribute('fallbackFile', ''); + } + /** Execute function */ - $executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST')); try { - $version = $function->getAttribute('version', 'v2'); - $command = $runtime['startCommand']; - $command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"'; + $version = match ($type) { + 'function' => $resource->getAttribute('version', 'v2'), + 'site' => 'v5', + }; + $entrypoint = match ($type) { + 'function' => $deployment->getAttribute('entrypoint', ''), + 'site' => '', + }; + + if ($type === 'function') { + $runtimeEntrypoint = match ($version) { + 'v2' => '', + default => 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $runtime['startCommand'] . '"' + }; + } elseif ($type === 'site') { + $frameworks = Config::getParam('frameworks', []); + $framework = $frameworks[$resource->getAttribute('framework', '')] ?? null; + + $startCommand = $runtime['startCommand']; + + if (!is_null($framework)) { + $adapter = ($framework['adapters'] ?? [])[$deployment->getAttribute('adapter', '')] ?? null; + if (!is_null($adapter) && isset($adapter['startCommand'])) { + $startCommand = $adapter['startCommand']; + } + } + + $runtimeEntrypoint = 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $startCommand . '"'; + } + + $entrypoint = match ($type) { + 'function' => $deployment->getAttribute('entrypoint', ''), + 'site' => '', + }; + $executionResponse = $executor->createExecution( projectId: $project->getId(), deploymentId: $deployment->getId(), body: \strlen($body) > 0 ? $body : null, variables: $vars, - timeout: $function->getAttribute('timeout', 0), + timeout: $resource->getAttribute('timeout', 30), image: $runtime['image'], - source: $build->getAttribute('path', ''), - entrypoint: $deployment->getAttribute('entrypoint', ''), + source: $deployment->getAttribute('buildPath', ''), + entrypoint: $entrypoint, version: $version, path: $path, method: $method, headers: $headers, - runtimeEntrypoint: $command, - cpus: $spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT, - memory: $spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT, - logging: $function->getAttribute('logging', true), + runtimeEntrypoint: $runtimeEntrypoint, + cpus: $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT, + memory: $spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT, + logging: $resource->getAttribute('logging', true), requestTimeout: 30 ); + // Branded 404 override + $isResponseBranded = false; + if ($executionResponse['statusCode'] === 404 && $deployment->getAttribute('adapter', '') === 'static') { + $layout = new View(__DIR__ . '/../views/general/404.phtml'); + $executionResponse['body'] = $layout->render(); + $executionResponse['headers']['content-length'] = \strlen($executionResponse['body']); + $isResponseBranded = true; + } + + // Branded banner for previews + if (!$isResponseBranded) { + if (\is_null($apiKey) || $apiKey->isBannerDisabled() === false) { + $transformation = new Transformation(); + $transformation->addAdapter(new Preview()); + $transformation->setInput($executionResponse['body']); + $transformation->setTraits($executionResponse['headers']); + if ($isPreview && $transformation->transform()) { + $executionResponse['body'] = $transformation->getOutput(); + + foreach ($executionResponse['headers'] as $key => $value) { + if (\strtolower($key) === 'content-length') { + $executionResponse['headers'][$key] = \strlen($executionResponse['body']); + } + } + } + } + } + + // Branded error pages (when developer left body empty) + if ($executionResponse['statusCode'] >= 400 && empty($executionResponse['body'])) { + $layout = new View($errorView); + $layout + ->setParam('title', $project->getAttribute('name') . ' - Error') + ->setParam('type', 'proxy_error_override') + ->setParam('code', $executionResponse['statusCode']); + + $executionResponse['body'] = $layout->render(); + foreach ($executionResponse['headers'] as $key => $value) { + if (\strtolower($key) === 'content-length') { + $executionResponse['headers'][$key] = \strlen($executionResponse['body']); + } elseif (\strtolower($key) === 'content-type') { + $executionResponse['headers'][$key] = 'text/html'; + } + } + } + $headersFiltered = []; foreach ($executionResponse['headers'] as $key => $value) { if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) { @@ -326,51 +566,38 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo /** Update execution status */ $status = $executionResponse['statusCode'] >= 500 ? 'failed' : 'completed'; $execution->setAttribute('status', $status); - $execution->setAttribute('responseStatusCode', $executionResponse['statusCode']); - $execution->setAttribute('responseHeaders', $headersFiltered); $execution->setAttribute('logs', $executionResponse['logs']); $execution->setAttribute('errors', $executionResponse['errors']); + $execution->setAttribute('responseStatusCode', $executionResponse['statusCode']); + $execution->setAttribute('responseHeaders', $headersFiltered); $execution->setAttribute('duration', $executionResponse['duration']); - } catch (\Throwable $th) { $durationEnd = \microtime(true); $execution ->setAttribute('duration', $durationEnd - $durationStart) - ->setAttribute('status', 'failed') - ->setAttribute('responseStatusCode', 500) - ->setAttribute('errors', $th->getMessage() . '\nError Code: ' . $th->getCode()); + ->setAttribute('responseStatusCode', 500); + + if ($type === 'function') { + $execution + ->setAttribute('status', 'failed') + ->setAttribute('errors', $th->getMessage() . '\nError Code: ' . $th->getCode()); + } Console::error($th->getMessage()); if ($th instanceof AppwriteException) { throw $th; } } finally { - $fileSize = 0; - $file = $request->getFiles('file'); - if (!empty($file)) { - $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; + if ($type === 'function') { + $queueForFunctions + ->setType(Func::TYPE_ASYNC_WRITE) + ->setExecution($execution) + ->setProject($project) + ->trigger(); + } elseif ($type === 'site') { // TODO: Move it to logs worker later + $dbForProject->createDocument('executions', $execution); } - - $queueForUsage - ->addMetric(METRIC_NETWORK_REQUESTS, 1) - ->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(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(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))) - ->setProject($project) - ->trigger() - ; - - $queueForFunctions - ->setType(Func::TYPE_ASYNC_WRITE) - ->setExecution($execution) - ->setProject($project) - ->trigger(); } $execution->setAttribute('logs', ''); @@ -392,7 +619,11 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $contentType = $header['value']; } - $response->setHeader($header['name'], $header['value']); + if (\strtolower($header['name']) === 'transfer-encoding') { + continue; + } + + $response->addHeader(\strtolower($header['name']), $header['value']); } $response @@ -400,19 +631,91 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo ->setStatusCode($execution['responseStatusCode'] ?? 200) ->send($body); + $fileSize = 0; + $file = $request->getFiles('file'); + if (!empty($file)) { + $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; + } + + if (!empty($apiKey) && !empty($apiKey->getDisabledMetrics())) { + foreach ($apiKey->getDisabledMetrics() as $key) { + $queueForStatsUsage->disableMetric($key); + } + } + + $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); + $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); + $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); + if ($deployment->getAttribute('resourceType') === 'sites') { + $queueForStatsUsage + ->disableMetric(METRIC_NETWORK_REQUESTS) + ->disableMetric(METRIC_NETWORK_INBOUND) + ->disableMetric(METRIC_NETWORK_OUTBOUND); + if ($resource->getAttribute('adapter') !== 'ssr') { + $queueForStatsUsage + ->disableMetric(METRIC_EXECUTIONS) + ->disableMetric(METRIC_EXECUTIONS_COMPUTE) + ->disableMetric(METRIC_EXECUTIONS_MB_SECONDS) + ->disableMetric($metricTypeExecutions) + ->disableMetric($metricTypeIdExecutions) + ->disableMetric($metricTypeExecutionsCompute) + ->disableMetric($metricTypeIdExecutionsCompute) + ->disableMetric($metricTypeExecutionsMbSeconds) + ->disableMetric($metricTypeIdExecutionsMBSeconds); + } + + $queueForStatsUsage + ->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()) + ; + } + + + $compute = (int)($execution->getAttribute('duration') * 1000); + $mbSeconds = (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT)); + $queueForStatsUsage + ->addMetric(METRIC_NETWORK_REQUESTS, 1) + ->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize) + ->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize()) + ->addMetric(METRIC_EXECUTIONS, 1) + ->addMetric($metricTypeExecutions, 1) + ->addMetric($metricTypeIdExecutions, 1) + ->addMetric(METRIC_EXECUTIONS_COMPUTE, $compute) // per project + ->addMetric($metricTypeExecutionsCompute, $compute) // per function + ->addMetric($metricTypeIdExecutionsCompute, $compute) // per function + ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, $mbSeconds) + ->addMetric($metricTypeExecutionsMbSeconds, $mbSeconds) + ->addMetric($metricTypeIdExecutionsMBSeconds, $mbSeconds) + ->setProject($project) + ->trigger(); + return true; } elseif ($type === 'api') { - $utopia->getRoute()?->label('error', ''); 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 { - throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Unknown resource type ' . $type); + throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Unknown resource type ' . $type, view: $errorView); } - $utopia->getRoute()?->label('error', ''); return false; } -/* App::init() ->groups(['api']) ->inject('project') @@ -422,10 +725,9 @@ App::init() throw new AppwriteException(AppwriteException::GENERAL_BAD_REQUEST, 'Admin mode is not allowed for console project'); } }); -*/ App::init() - ->groups(['database', 'functions', 'storage', 'messaging']) + ->groups(['database', 'functions', 'sites', 'messaging']) ->inject('project') ->inject('request') ->action(function (Document $project, Request $request) { @@ -445,27 +747,30 @@ App::init() ->inject('response') ->inject('console') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('locale') ->inject('localeCodes') ->inject('clients') ->inject('geodb') - ->inject('queueForUsage') + ->inject('queueForStatsUsage') ->inject('queueForEvents') ->inject('queueForCertificates') ->inject('queueForFunctions') + ->inject('executor') ->inject('isResourceBlocked') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForConsole, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked) { + ->inject('previewHostname') + ->inject('apiKey') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, StatsUsage $queueForStatsUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, Executor $executor, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { /* * Appwrite Router */ $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain - if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked)) { - return; + if ($host !== $mainDomain || !empty($previewHostname)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { + $utopia->getRoute()?->label('router', true); } } @@ -492,6 +797,9 @@ App::init() if (version_compare($requestFormat, '1.6.0', '<')) { $request->addFilter(new RequestV18()); } + if (version_compare($requestFormat, '1.7.0', '<')) { + $request->addFilter(new RequestV19()); + } } $domain = $request->getHostname(); @@ -512,26 +820,49 @@ App::init() if (!empty($envDomain) && $envDomain !== 'localhost') { $mainDomain = $envDomain; } else { - $domainDocument = $dbForConsole->getDocument('rules', md5($envDomain)); + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { + $domainDocument = $dbForPlatform->getDocument('rules', md5($envDomain)); + } else { + $domainDocument = $dbForPlatform->findOne('rules', [Query::orderAsc('$id')]); + } $mainDomain = !$domainDocument->isEmpty() ? $domainDocument->getAttribute('domain') : $domain->get(); } if ($mainDomain !== $domain->get()) { Console::warning($domain->get() . ' is not a main domain. Skipping SSL certificate generation.'); } else { - $domainDocument = $dbForConsole->getDocument('rules', md5($domain->get())); + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { + $domainDocument = $dbForPlatform->getDocument('rules', md5($domain->get())); + } else { + $domainDocument = $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$domain->get()]) + ]); + } + + $owner = ''; + $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + if (!empty($functionsDomain) && \str_ends_with($domain->get(), $functionsDomain)) { + $owner = 'Appwrite'; + } if ($domainDocument->isEmpty()) { + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique(); $domainDocument = new Document([ - '$id' => md5($domain->get()), + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + '$id' => $ruleId, 'domain' => $domain->get(), - 'resourceType' => 'api', + 'type' => 'api', 'status' => 'verifying', - 'projectId' => 'console', - 'projectInternalId' => 'console' + 'projectId' => $console->getId(), + 'projectInternalId' => $console->getInternalId(), + 'search' => implode(' ', [$ruleId, $domain->get()]), + 'owner' => $owner, + 'region' => $console->getAttribute('region') ]); - $domainDocument = $dbForConsole->createDocument('rules', $domainDocument); + $domainDocument = $dbForPlatform->createDocument('rules', $domainDocument); Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); @@ -562,6 +893,22 @@ App::init() $validator = new Hostname($clients); if ($validator->isValid($origin)) { $refDomainOrigin = $origin; + } elseif (!empty($origin)) { + // Auto-allow domains with linked rule + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { + $rule = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', md5($origin ?? ''))); + } else { + $rule = Authorization::skip( + fn () => $dbForPlatform->find('rules', [ + Query::equal('domain', [$origin]), + Query::limit(1) + ]) + )[0] ?? new Document(); + } + + if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getInternalId()) { + $refDomainOrigin = $origin; + } } $refDomain = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $refDomainOrigin . (!empty($port) ? ':' . $port : ''); @@ -610,8 +957,11 @@ App::init() if (version_compare($responseFormat, '1.6.0', '<')) { $response->addFilter(new ResponseV18()); } + if (version_compare($responseFormat, '1.7.0', '<')) { + $response->addFilter(new ResponseV19()); + } if (version_compare($responseFormat, APP_VERSION_STABLE, '>')) { - $response->addHeader('X-Appwrite-Warning', "The current SDK is built for Appwrite " . $responseFormat . ". However, the current Appwrite server version is ". APP_VERSION_STABLE . ". Please downgrade your SDK to match the Appwrite version: https://appwrite.io/docs/sdks"); + $response->addHeader('X-Appwrite-Warning', "The current SDK is built for Appwrite " . $responseFormat . ". However, the current Appwrite server version is " . APP_VERSION_STABLE . ". Please downgrade your SDK to match the Appwrite version: https://appwrite.io/docs/sdks"); } } @@ -667,23 +1017,27 @@ App::options() ->inject('swooleRequest') ->inject('request') ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') - ->inject('queueForUsage') + ->inject('queueForStatsUsage') ->inject('queueForFunctions') + ->inject('executor') ->inject('geodb') ->inject('isResourceBlocked') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked) { + ->inject('previewHostname') + ->inject('project') + ->inject('apiKey') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, ?Key $apiKey) { /* * Appwrite Router */ $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); // Only run Router when external domain - if ($host !== $mainDomain) { - if (router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked)) { - return; + if ($host !== $mainDomain || !empty($previewHostname)) { + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { + $utopia->getRoute()?->label('router', true); } } @@ -697,6 +1051,16 @@ App::options() ->addHeader('Access-Control-Allow-Origin', $origin) ->addHeader('Access-Control-Allow-Credentials', 'true') ->noContent(); + + /** OPTIONS requests in utopia do not execute shutdown handlers, as a result we need to track the OPTIONS requests explicitly + * @see https://github.com/utopia-php/http/blob/0.33.16/src/App.php#L825-L855 + */ + $queueForStatsUsage + ->addMetric(METRIC_NETWORK_REQUESTS, 1) + ->addMetric(METRIC_NETWORK_INBOUND, $request->getSize()) + ->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize()) + ->setProject($project) + ->trigger(); }); App::error() @@ -707,8 +1071,8 @@ App::error() ->inject('project') ->inject('logger') ->inject('log') - ->inject('queueForUsage') - ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, Usage $queueForUsage) { + ->inject('queueForStatsUsage') + ->action(function (Throwable $error, App $utopia, Request $request, Response $response, Document $project, ?Logger $logger, Log $log, StatsUsage $queueForStatsUsage) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); $route = $utopia->getRoute(); $class = \get_class($error); @@ -770,6 +1134,10 @@ App::error() break; case 'Utopia\Database\Exception\NotFound': $error = new AppwriteException(AppwriteException::COLLECTION_NOT_FOUND, $error->getMessage(), previous: $error); + break; + case 'Utopia\Database\Exception\Dependency': + $error = new AppwriteException(AppwriteException::INDEX_DEPENDENCY, null, previous: $error); + break; } $code = $error->getCode(); @@ -781,23 +1149,22 @@ App::error() $publish = $error->getCode() === 0 || $error->getCode() >= 500; } - if ($error->getCode() >= 400 && $error->getCode() < 500) { + $providerConfig = System::getEnv('_APP_EXPERIMENT_LOGGING_CONFIG', ''); + if (!empty($providerConfig) && $error->getCode() >= 400 && $error->getCode() < 500) { // Register error logger - $providerName = System::getEnv('_APP_EXPERIMENT_LOGGING_PROVIDER', ''); - $providerConfig = System::getEnv('_APP_EXPERIMENT_LOGGING_CONFIG', ''); - try { - $loggingProvider = new DSN($providerConfig ?? ''); + $loggingProvider = new DSN($providerConfig); $providerName = $loggingProvider->getScheme(); if (!empty($providerName) && $providerName === 'sentry') { $key = $loggingProvider->getPassword(); $projectId = $loggingProvider->getUser() ?? ''; $host = 'https://' . $loggingProvider->getHost(); + $sampleRate = $loggingProvider->getParam('sample', 0.01); $adapter = new Sentry($projectId, $key, $host); $logger = new Logger($adapter); - $logger->setSample(0.04); + $logger->setSample($sampleRate); $publish = true; } else { throw new \Exception('Invalid experimental logging provider'); @@ -807,7 +1174,10 @@ App::error() } } - if ($publish && $project->getId() !== 'console') { + /** + * If its not a publishable error, track usage stats. Publishable errors are >= 500 or those explicitly marked as publish=true in errors.php + */ + if (!$publish && $project->getId() !== 'console') { if (!Auth::isPrivilegedUser(Authorization::getRoles())) { $fileSize = 0; $file = $request->getFiles('file'); @@ -815,18 +1185,17 @@ App::error() $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; } - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_NETWORK_REQUESTS, 1) ->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize) ->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize()); } - $queueForUsage + $queueForStatsUsage ->setProject($project) ->trigger(); } - if ($logger && $publish) { try { /** @var Utopia\Database\Document $user */ @@ -837,6 +1206,8 @@ App::error() if (isset($user) && !$user->isEmpty()) { $log->setUser(new User($user->getId())); + } else { + $log->setUser(new User('guest-' . hash('sha256', $request->getIP()))); } try { @@ -847,14 +1218,14 @@ App::error() } $log->setNamespace("http"); - $log->setServer(\gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); $log->addTag('database', $dsn->getHost()); $log->addTag('method', $route->getMethod()); - $log->addTag('url', $route->getPath()); + $log->addTag('url', $request->getURI()); $log->addTag('verboseType', get_class($error)); $log->addTag('code', $error->getCode()); $log->addTag('projectId', $project->getId()); @@ -866,8 +1237,14 @@ App::error() $log->addExtra('trace', $error->getTraceAsString()); $log->addExtra('roles', Authorization::getRoles()); - $action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD"); + $action = 'UNKNOWN_NAMESPACE.UNKNOWN.METHOD'; + if (!empty($sdk)) { + /** @var Appwrite\SDK\Method $sdk */ + $action = $sdk->getNamespace() . '.' . $sdk->getMethodName(); + } + $log->setAction($action); + $log->addTag('service', $action); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); @@ -930,9 +1307,14 @@ App::error() ->addHeader('Pragma', 'no-cache') ->setStatusCode($code); - $template = ($route) ? $route->getLabel('error', null) : null; + $template = $error->getView() ?? (($route) ? $route->getLabel('error', null) : null); - if ($template) { + // TODO: Ideally use group 'api' here, but all wildcard routes seem to have 'api' at the moment + if (!\str_starts_with($route->getPath(), '/v1')) { + $template = __DIR__ . '/../views/general/error.phtml'; + } + + if (!empty($template)) { $layout = new View($template); $layout @@ -943,9 +1325,11 @@ App::error() ->setParam('message', $output['message'] ?? '') ->setParam('type', $output['type'] ?? '') ->setParam('code', $output['code'] ?? '') - ->setParam('trace', $output['trace'] ?? []); + ->setParam('trace', $output['trace'] ?? []) + ->setParam('exception', $error); $response->html($layout->render()); + return; } $response->dynamic( @@ -962,22 +1346,27 @@ App::get('/robots.txt') ->inject('swooleRequest') ->inject('request') ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') - ->inject('queueForUsage') + ->inject('queueForStatsUsage') ->inject('queueForFunctions') + ->inject('executor') ->inject('geodb') ->inject('isResourceBlocked') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked) { + ->inject('previewHostname') + ->inject('apiKey') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); - if ($host === $mainDomain || $host === 'localhost') { + if (($host === $mainDomain || $host === 'localhost') && empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/robots.phtml'); $response->text($template->render(false)); } else { - router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked); + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { + $utopia->getRoute()?->label('router', true); + } } }); @@ -989,22 +1378,27 @@ App::get('/humans.txt') ->inject('swooleRequest') ->inject('request') ->inject('response') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('queueForEvents') - ->inject('queueForUsage') + ->inject('queueForStatsUsage') ->inject('queueForFunctions') + ->inject('executor') ->inject('geodb') ->inject('isResourceBlocked') - ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForConsole, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked) { + ->inject('previewHostname') + ->inject('apiKey') + ->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, ?Key $apiKey) { $host = $request->getHostname() ?? ''; $mainDomain = System::getEnv('_APP_DOMAIN', ''); - if ($host === $mainDomain || $host === 'localhost') { + if (($host === $mainDomain || $host === 'localhost') && empty($previewHostname)) { $template = new View(__DIR__ . '/../views/general/humans.phtml'); $response->text($template->render(false)); } else { - router($utopia, $dbForConsole, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked); + if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForStatsUsage, $queueForFunctions, $executor, $geodb, $isResourceBlocked, $previewHostname, $apiKey)) { + $utopia->getRoute()?->label('router', true); + } } }); @@ -1066,12 +1460,27 @@ App::get('/v1/ping') ->desc('Test the connection between the Appwrite and the SDK.') ->label('scope', 'global') ->label('event', 'projects.[projectId].ping') + ->label('sdk', new Method( + namespace: 'ping', + name: 'get', + hide: true, + description: <<<EOT + Send a ping to project as part of onboarding. + EOT, + auth: [], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_ANY, + ) + ], + )) ->inject('response') ->inject('project') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForEvents') - ->action(function (Response $response, Document $project, Database $dbForConsole, Event $queueForEvents) { - if ($project->isEmpty()) { + ->action(function (Response $response, Document $project, Database $dbForPlatform, Event $queueForEvents) { + if ($project->isEmpty() || $project->getId() === 'console') { throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND); } @@ -1082,8 +1491,8 @@ App::get('/v1/ping') ->setAttribute('pingCount', $pingCount) ->setAttribute('pingedAt', $pingedAt); - Authorization::skip(function () use ($dbForConsole, $project) { - $dbForConsole->updateDocument('projects', $project->getId(), $project); + Authorization::skip(function () use ($dbForPlatform, $project) { + $dbForPlatform->updateDocument('projects', $project->getId(), $project); }); $queueForEvents @@ -1093,6 +1502,34 @@ App::get('/v1/ping') $response->text('Pong!'); }); +// Preview authorization +App::get('/_appwrite/authorize') + ->inject('request') + ->inject('response') + ->inject('previewHostname') + ->action(function (Request $request, Response $response, string $previewHostname) { + + $host = $request->getHostname() ?? ''; + if (!empty($previewHostname)) { + $host = $previewHostname; + } + + $referrer = $request->getReferer(); + $protocol = \parse_url($request->getOrigin($referrer), PHP_URL_SCHEME); + + $jwt = $request->getParam('jwt', ''); + $path = $request->getParam('path', ''); + + $duration = 60 * 60 * 24; // 1 day in seconds + $expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), $duration)); + + $response + ->addCookie(Auth::$cookieNamePreview, $jwt, (new \DateTime($expire))->getTimestamp(), '/', $host, ('https' === $protocol), true, null) + ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') + ->addHeader('Pragma', 'no-cache') + ->redirect($protocol . '://' . $host . $path); + }); + App::wildcard() ->groups(['api']) ->label('scope', 'global') @@ -1101,5 +1538,16 @@ App::wildcard() }); foreach (Config::getParam('services', []) as $service) { - include_once $service['controller']; + if (!empty($service['controller'])) { + include_once $service['controller']; + } +} + +// Modules +$platform = new Appwrite(); +$platform->init(Service::TYPE_HTTP); + +// Check for any errors found while we were initialising the SDK Methods. +if (!empty(Method::getErrors())) { + throw new \Exception('Errors found during SDK initialization:' . PHP_EOL . implode(PHP_EOL, Method::getErrors())); } diff --git a/app/controllers/mock.php b/app/controllers/mock.php index bc071fc885..16d8e03841 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -24,7 +24,7 @@ App::get('/v1/mock/tests/general/oauth2') ->groups(['mock']) ->label('scope', 'public') ->label('docs', false) - ->label('sdk.mock', true) + ->label('mock', true) ->param('client_id', '', new Text(100), 'OAuth2 Client ID.') ->param('redirect_uri', '', new Host(['localhost']), 'OAuth2 Redirect URI.') // Important to deny an open redirect attack ->param('scope', '', new Text(100), 'OAuth2 scope list.') @@ -40,7 +40,7 @@ App::get('/v1/mock/tests/general/oauth2/token') ->groups(['mock']) ->label('scope', 'public') ->label('docs', false) - ->label('sdk.mock', true) + ->label('mock', true) ->param('client_id', '', new Text(100), 'OAuth2 Client ID.') ->param('client_secret', '', new Text(100), 'OAuth2 scope list.') ->param('grant_type', 'authorization_code', new WhiteList(['refresh_token', 'authorization_code']), 'OAuth2 Grant Type.', true) @@ -162,15 +162,15 @@ App::post('/v1/mock/api-key-unprefixed') ->label('docs', false) ->param('projectId', '', new UID(), 'Project ID.') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $projectId, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $projectId, Response $response, Database $dbForPlatform) { $isDevelopment = System::getEnv('_APP_ENV', 'development') === 'development'; if (!$isDevelopment) { throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); } - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); @@ -195,9 +195,9 @@ App::post('/v1/mock/api-key-unprefixed') 'secret' => \bin2hex(\random_bytes(128)), ]); - $key = $dbForConsole->createDocument('keys', $key); + $key = $dbForPlatform->createDocument('keys', $key); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $response ->setStatusCode(Response::STATUS_CODE_CREATED) @@ -214,15 +214,15 @@ App::get('/v1/mock/github/callback') ->inject('gitHub') ->inject('project') ->inject('response') - ->inject('dbForConsole') - ->action(function (string $providerInstallationId, string $projectId, GitHub $github, Document $project, Response $response, Database $dbForConsole) { + ->inject('dbForPlatform') + ->action(function (string $providerInstallationId, string $projectId, GitHub $github, Document $project, Response $response, Database $dbForPlatform) { $isDevelopment = System::getEnv('_APP_ENV', 'development') === 'development'; if (!$isDevelopment) { throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED); } - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { $error = 'Project with the ID from state could not be found.'; @@ -256,7 +256,7 @@ App::get('/v1/mock/github/callback') 'personal' => false ]); - $installation = $dbForConsole->createDocument('installations', $installation); + $installation = $dbForPlatform->createDocument('installations', $installation); } $response->json([ diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index f5921bf6e8..957a7a7d23 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -1,8 +1,7 @@ <?php -use Ahc\Jwt\JWT; -use Ahc\Jwt\JWTException; use Appwrite\Auth\Auth; +use Appwrite\Auth\Key; use Appwrite\Auth\MFA\Type\TOTP; use Appwrite\Event\Audit; use Appwrite\Event\Build; @@ -12,14 +11,14 @@ use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\Messaging; use Appwrite\Event\Realtime; -use Appwrite\Event\Usage; +use Appwrite\Event\StatsUsage; use Appwrite\Event\Webhook; use Appwrite\Extend\Exception; use Appwrite\Extend\Exception as AppwriteException; +use Appwrite\SDK\Method; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; use Utopia\App; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -29,7 +28,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; use Utopia\System\System; use Utopia\Validator\WhiteList; @@ -59,7 +58,7 @@ $parseLabel = function (string $label, array $responsePayload, array $requestPar return $label; }; -$eventDatabaseListener = function (Document $document, Response $response, Event $queueForEvents, Func $queueForFunctions, Webhook $queueForWebhooks, Realtime $queueForRealtime) { +$eventDatabaseListener = function (Document $project, Document $document, Response $response, Event $queueForEvents, Func $queueForFunctions, Webhook $queueForWebhooks, Realtime $queueForRealtime) { // Only trigger events for user creation with the database listener. if ($document->getCollection() !== 'users') { return; @@ -75,20 +74,23 @@ $eventDatabaseListener = function (Document $document, Response $response, Event ->from($queueForEvents) ->trigger(); - $queueForWebhooks - ->from($queueForEvents) - ->trigger(); - if ($queueForEvents->getProject()->getId() === 'console') { - return; + /** Trigger webhooks events only if a project has them enabled */ + if (!empty($project->getAttribute('webhooks'))) { + $queueForWebhooks + ->from($queueForEvents) + ->trigger(); } - $queueForRealtime - ->from($queueForEvents) - ->trigger(); + /** Trigger realtime events only for non console events */ + if ($queueForEvents->getProject()->getId() !== 'console') { + $queueForRealtime + ->from($queueForEvents) + ->trigger(); + } }; -$usageDatabaseListener = function (string $event, Document $document, Usage $queueForUsage) { +$usageDatabaseListener = function (string $event, Document $document, StatsUsage $queueForStatsUsage) { $value = 1; if ($event === Database::EVENT_DOCUMENT_DELETE) { $value = -1; @@ -96,84 +98,87 @@ $usageDatabaseListener = function (string $event, Document $document, Usage $que switch (true) { case $document->getCollection() === 'teams': - $queueForUsage - ->addMetric(METRIC_TEAMS, $value); // per project + $queueForStatsUsage->addMetric(METRIC_TEAMS, $value); // per project break; case $document->getCollection() === 'users': - $queueForUsage - ->addMetric(METRIC_USERS, $value); // per project + $queueForStatsUsage->addMetric(METRIC_USERS, $value); // per project if ($event === Database::EVENT_DOCUMENT_DELETE) { - $queueForUsage - ->addReduce($document); + $queueForStatsUsage->addReduce($document); } break; case $document->getCollection() === 'sessions': // sessions - $queueForUsage - ->addMetric(METRIC_SESSIONS, $value); //per project + $queueForStatsUsage->addMetric(METRIC_SESSIONS, $value); //per project break; case $document->getCollection() === 'databases': // databases - $queueForUsage - ->addMetric(METRIC_DATABASES, $value); // per project + $queueForStatsUsage->addMetric(METRIC_DATABASES, $value); // per project if ($event === Database::EVENT_DOCUMENT_DELETE) { - $queueForUsage - ->addReduce($document); + $queueForStatsUsage->addReduce($document); } break; case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections $parts = explode('_', $document->getCollection()); $databaseInternalId = $parts[1] ?? 0; - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_COLLECTIONS, $value) // per project - ->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_COLLECTIONS), $value) - ; + ->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_COLLECTIONS), $value); if ($event === Database::EVENT_DOCUMENT_DELETE) { - $queueForUsage - ->addReduce($document); + $queueForStatsUsage->addReduce($document); } break; case str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_'): //documents $parts = explode('_', $document->getCollection()); $databaseInternalId = $parts[1] ?? 0; $collectionInternalId = $parts[3] ?? 0; - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_DOCUMENTS, $value) // per project ->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_DOCUMENTS), $value) // per database ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), $value); // per collection break; case $document->getCollection() === 'buckets': //buckets - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_BUCKETS, $value); // per project if ($event === Database::EVENT_DOCUMENT_DELETE) { - $queueForUsage + $queueForStatsUsage ->addReduce($document); } break; case str_starts_with($document->getCollection(), 'bucket_'): // files $parts = explode('_', $document->getCollection()); $bucketInternalId = $parts[1]; - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_FILES, $value) // per project ->addMetric(METRIC_FILES_STORAGE, $document->getAttribute('sizeOriginal') * $value) // per project ->addMetric(str_replace('{bucketInternalId}', $bucketInternalId, METRIC_BUCKET_ID_FILES), $value) // per bucket ->addMetric(str_replace('{bucketInternalId}', $bucketInternalId, METRIC_BUCKET_ID_FILES_STORAGE), $document->getAttribute('sizeOriginal') * $value); // per bucket break; case $document->getCollection() === 'functions': - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_FUNCTIONS, $value); // per project if ($event === Database::EVENT_DOCUMENT_DELETE) { - $queueForUsage + $queueForStatsUsage + ->addReduce($document); + } + break; + case $document->getCollection() === 'sites': + $queueForStatsUsage + ->addMetric(METRIC_SITES, $value); // per project + + if ($event === Database::EVENT_DOCUMENT_DELETE) { + $queueForStatsUsage ->addReduce($document); } break; case $document->getCollection() === 'deployments': - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_DEPLOYMENTS, $value) // per project ->addMetric(METRIC_DEPLOYMENTS_STORAGE, $document->getAttribute('size') * $value) // per project - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS), $value) // per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value); + ->addMetric(str_replace(['{resourceType}'], [$document->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_DEPLOYMENTS), $value) // per function + ->addMetric(str_replace(['{resourceType}'], [$document->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $value) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value); break; default: break; @@ -184,127 +189,96 @@ App::init() ->groups(['api']) ->inject('utopia') ->inject('request') - ->inject('dbForConsole') + ->inject('dbForPlatform') + ->inject('dbForProject') + ->inject('queueForAudits') ->inject('project') ->inject('user') ->inject('session') ->inject('servers') ->inject('mode') ->inject('team') - ->action(function (App $utopia, Request $request, Database $dbForConsole, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team) { + ->inject('apiKey') + ->action(function (App $utopia, Request $request, Database $dbForPlatform, Database $dbForProject, Audit $queueForAudits, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team, ?Key $apiKey) { $route = $utopia->getRoute(); if ($project->isEmpty()) { throw new Exception(Exception::PROJECT_NOT_FOUND); } - /** Default role */ $roles = Config::getParam('roles', []); - $role = ($user->isEmpty()) + + $role = $user->isEmpty() ? Role::guests()->toString() : Role::users()->toString(); - /** Allowed Scopes for the role */ $scopes = $roles[$role]['scopes']; - $apiKey = $request->getHeader('x-appwrite-key', ''); - // API Key authentication if (!empty($apiKey)) { - // Do not allow API key and session to be set at the same time if (!$user->isEmpty()) { throw new Exception(Exception::USER_API_KEY_AND_SESSION_SET); } - - // Remove after migration - if (!\str_contains($apiKey, '_')) { - $keyType = API_KEY_STANDARD; - $authKey = $apiKey; - } else { - [ $keyType, $authKey ] = \explode('_', $apiKey, 2); + if ($apiKey->isExpired()) { + throw new Exception(Exception::PROJECT_KEY_EXPIRED); } - if ($keyType === API_KEY_DYNAMIC) { - // Dynamic key + $role = $apiKey->getRole(); + $scopes = $apiKey->getScopes(); - $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); + // Disable authorization checks for API keys + Authorization::setDefaultStatus(false); - try { - $payload = $jwtObj->decode($authKey); - } catch (JWTException $error) { - throw new Exception(Exception::API_KEY_EXPIRED); - } + if ($apiKey->getRole() === Auth::USER_ROLE_APPS) { + $user = new Document([ + '$id' => '', + 'status' => true, + 'type' => Auth::ACTIVITY_TYPE_APP, + 'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(), + 'password' => '', + 'name' => $apiKey->getName(), + ]); - $projectId = $payload['projectId'] ?? ''; - $tokenScopes = $payload['scopes'] ?? []; + $queueForAudits->setUser($user); + } - // JWT includes project ID for better security - if ($projectId === $project->getId()) { - $user = new Document([ - '$id' => '', - 'status' => true, - 'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(), - 'password' => '', - 'name' => $project->getAttribute('name', 'Untitled'), - ]); + if ($apiKey->getType() === API_KEY_STANDARD) { + $dbKey = $project->find( + key: 'secret', + find: $request->getHeader('x-appwrite-key', ''), + subject: 'keys' + ); - $role = Auth::USER_ROLE_APPS; - $scopes = \array_merge($roles[$role]['scopes'], $tokenScopes); + if ($dbKey) { + $accessedAt = $dbKey->getAttribute('accessedAt', ''); - Authorization::setRole(Auth::USER_ROLE_APPS); - Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. - } - } elseif ($keyType === API_KEY_STANDARD) { - // No underline means no prefix. Backwards compatibility. - // Regular key - - // Check if given key match project API keys - $key = $project->find('secret', $apiKey, 'keys'); - if ($key) { - $user = new Document([ - '$id' => '', - 'status' => true, - 'email' => 'app.' . $project->getId() . '@service.' . $request->getHostname(), - 'password' => '', - 'name' => $project->getAttribute('name', 'Untitled'), - ]); - - $role = Auth::USER_ROLE_APPS; - $scopes = \array_merge($roles[$role]['scopes'], $key->getAttribute('scopes', [])); - - $expire = $key->getAttribute('expire'); - if (!empty($expire) && $expire < DateTime::formatTz(DateTime::now())) { - throw new Exception(Exception::PROJECT_KEY_EXPIRED); - } - - Authorization::setRole(Auth::USER_ROLE_APPS); - Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys. - - $accessedAt = $key->getAttribute('accessedAt', ''); if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_KEY_ACCESS)) > $accessedAt) { - $key->setAttribute('accessedAt', DateTime::now()); - $dbForConsole->updateDocument('keys', $key->getId(), $key); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbKey->setAttribute('accessedAt', DateTime::now()); + $dbForPlatform->updateDocument('keys', $dbKey->getId(), $dbKey); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } $sdkValidator = new WhiteList($servers, true); $sdk = $request->getHeader('x-sdk-name', 'UNKNOWN'); + if ($sdkValidator->isValid($sdk)) { - $sdks = $key->getAttribute('sdks', []); + $sdks = $dbKey->getAttribute('sdks', []); + if (!in_array($sdk, $sdks)) { - array_push($sdks, $sdk); - $key->setAttribute('sdks', $sdks); + $sdks[] = $sdk; + $dbKey->setAttribute('sdks', $sdks); /** Update access time as well */ - $key->setAttribute('accessedAt', Datetime::now()); - $dbForConsole->updateDocument('keys', $key->getId(), $key); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbKey->setAttribute('accessedAt', Datetime::now()); + $dbForPlatform->updateDocument('keys', $dbKey->getId(), $dbKey); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); } } + + $queueForAudits->setUser($user); } } - } - // Admin User Authentication + } // Admin User Authentication elseif (($project->getId() === 'console' && !$team->isEmpty() && !$user->isEmpty()) || ($project->getId() !== 'console' && !$user->isEmpty() && $mode === APP_MODE_ADMIN)) { $teamId = $team->getId(); $adminRoles = []; @@ -320,7 +294,7 @@ App::init() throw new Exception(Exception::USER_UNAUTHORIZED); } - $scopes = []; // reset scope if admin + $scopes = []; // Reset scope if admin foreach ($adminRoles as $role) { $scopes = \array_merge($scopes, $roles[$role]['scopes']); } @@ -335,25 +309,57 @@ App::init() Authorization::setRole($authRole); } - /** Do not allow access to disabled services */ - $service = $route->getLabel('sdk.namespace', ''); - if (!empty($service)) { + // Update project last activity + if (!$project->isEmpty() && $project->getId() !== 'console') { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + } + } + + // Update user last activity + if (!empty($user->getId())) { + $accessedAt = $user->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCESS)) > $accessedAt) { + $user->setAttribute('accessedAt', DateTime::now()); + + if (APP_MODE_ADMIN !== $mode) { + $dbForProject->updateDocument('users', $user->getId(), $user); + } else { + $dbForPlatform->updateDocument('users', $user->getId(), $user); + } + } + } + + /** + * @var ?Method $method + */ + $method = $route->getLabel('sdk', false); + + if (\is_array($method)) { + $method = $method[0]; + } + + if (!empty($method)) { + $namespace = $method->getNamespace(); + if ( - array_key_exists($service, $project->getAttribute('services', [])) - && !$project->getAttribute('services', [])[$service] + array_key_exists($namespace, $project->getAttribute('services', [])) + && !$project->getAttribute('services', [])[$namespace] && !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles())) ) { throw new Exception(Exception::GENERAL_SERVICE_DISABLED); } } - /** Do now allow access if scope is not allowed */ + // Do now allow access if scope is not allowed $scope = $route->getLabel('scope', 'none'); if (!\in_array($scope, $scopes)) { throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE, $user->getAttribute('email', 'User') . ' (role: ' . \strtolower($roles[$role]['label']) . ') missing scope (' . $scope . ')'); } - /** Do not allow access to blocked accounts */ + // Do not allow access to blocked accounts if (false === $user->getAttribute('status')) { // Account is blocked throw new Exception(Exception::USER_BLOCKED); } @@ -383,17 +389,20 @@ App::init() ->inject('response') ->inject('project') ->inject('user') - ->inject('queue') + ->inject('publisher') ->inject('queueForEvents') ->inject('queueForMessaging') ->inject('queueForAudits') ->inject('queueForDeletes') ->inject('queueForDatabase') ->inject('queueForBuilds') - ->inject('queueForUsage') + ->inject('queueForStatsUsage') ->inject('dbForProject') + ->inject('timelimit') ->inject('mode') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Connection $queue, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Usage $queueForUsage, Database $dbForProject, string $mode) use ($usageDatabaseListener, $eventDatabaseListener) { + ->inject('apiKey') + ->inject('plan') + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Publisher $publisher, Event $queueForEvents, Messaging $queueForMessaging, Audit $queueForAudits, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, StatsUsage $queueForStatsUsage, Database $dbForProject, callable $timelimit, string $mode, ?Key $apiKey, array $plan) use ($usageDatabaseListener, $eventDatabaseListener) { $route = $utopia->getRoute(); @@ -416,7 +425,7 @@ App::init() foreach ($abuseKeyLabel as $abuseKey) { $start = $request->getContentRangeStart(); $end = $request->getContentRangeEnd(); - $timeLimit = new TimeLimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForProject); + $timeLimit = $timelimit($abuseKey, $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600)); $timeLimit ->setParam('{projectId}', $project->getId()) ->setParam('{userId}', $user->getId()) @@ -424,7 +433,7 @@ App::init() ->setParam('{ip}', $request->getIP()) ->setParam('{url}', $request->getHostname() . $route->getPath()) ->setParam('{method}', $request->getMethod()) - ->setParam('{chunkId}', (int) ($start / ($end + 1 - $start))); + ->setParam('{chunkId}', (int)($start / ($end + 1 - $start))); $timeLimitArray[] = $timeLimit; } @@ -444,7 +453,7 @@ App::init() $abuse = new Abuse($timeLimit); $remaining = $timeLimit->remaining(); $limit = $timeLimit->limit(); - $time = (new \DateTime($timeLimit->time()))->getTimestamp() + $route->getLabel('abuse-time', 3600); + $time = $timeLimit->time() + $route->getLabel('abuse-time', 3600); if ($limit && ($remaining < $closestLimit || is_null($closestLimit))) { $closestLimit = $remaining; @@ -478,9 +487,23 @@ App::init() ->setMode($mode) ->setUserAgent($request->getUserAgent('')) ->setIP($request->getIP()) + ->setHostname($request->getHostname()) ->setEvent($route->getLabel('audits.event', '')) - ->setProject($project) - ->setUser($user); + ->setProject($project); + + /* If a session exists, use the user associated with the session */ + if (!$user->isEmpty()) { + $userClone = clone $user; + // $user doesn't support `type` and can cause unintended effects. + $userClone->setAttribute('type', Auth::ACTIVITY_TYPE_USER); + $queueForAudits->setUser($userClone); + } + + if (!empty($apiKey) && !empty($apiKey->getDisabledMetrics())) { + foreach ($apiKey->getDisabledMetrics() as $key) { + $queueForStatsUsage->disableMetric($key); + } + } $queueForDeletes->setProject($project); $queueForDatabase->setProject($project); @@ -489,15 +512,16 @@ App::init() // Clone the queues, to prevent events triggered by the database listener // from overwriting the events that are supposed to be triggered in the shutdown hook. - $queueForEventsClone = new Event($queue); - $queueForFunctions = new Func($queue); - $queueForWebhooks = new Webhook($queue); + $queueForEventsClone = new Event($publisher); + $queueForFunctions = new Func($publisher); + $queueForWebhooks = new Webhook($publisher); $queueForRealtime = new Realtime(); $dbForProject - ->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForUsage)) - ->on(Database::EVENT_DOCUMENT_DELETE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForUsage)) + ->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage)) + ->on(Database::EVENT_DOCUMENT_DELETE, 'calculate-usage', fn ($event, $document) => $usageDatabaseListener($event, $document, $queueForStatsUsage)) ->on(Database::EVENT_DOCUMENT_CREATE, 'create-trigger-events', fn ($event, $document) => $eventDatabaseListener( + $project, $document, $response, $queueForEventsClone->from($queueForEvents), @@ -508,6 +532,10 @@ App::init() $useCache = $route->getLabel('cache', false); if ($useCache) { + $route = $utopia->match($request); + $isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview'; + $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !Auth::isPrivilegedUser(Authorization::getRoles()); + $key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER); $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( @@ -520,14 +548,11 @@ App::init() $parts = explode('/', $cacheLog->getAttribute('resourceType')); $type = $parts[0] ?? null; - if ($type === 'bucket') { + if ($type === 'bucket' && (!$isImageTransformation || !$isDisabled)) { $bucketId = $parts[1] ?? null; - $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); + $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isAPIKey = Auth::isAppUser(Authorization::getRoles()); - $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); - - if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && !$isAppUser && !$isPrivilegedUser)) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -551,20 +576,29 @@ App::init() if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } + //Do not update transformedAt if it's a console user + if (!Auth::isPrivilegedUser(Authorization::getRoles())) { + $transformedAt = $file->getAttribute('transformedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $transformedAt) { + $file->setAttribute('transformedAt', DateTime::now()); + Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $file->getAttribute('bucketInternalId'), $file->getId(), $file)); + } + } } $response ->addHeader('Cache-Control', sprintf('private, max-age=%d', $timestamp)) ->addHeader('X-Appwrite-Cache', 'hit') - ->setContentType($cacheLog->getAttribute('mimeType')) - ->send($data); + ->setContentType($cacheLog->getAttribute('mimeType')); + if (!$isImageTransformation || !$isDisabled) { + $response->send($data); + } } else { $response ->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') ->addHeader('Pragma', 'no-cache') ->addHeader('Expires', '0') - ->addHeader('X-Appwrite-Cache', 'miss') - ; + ->addHeader('X-Appwrite-Cache', 'miss'); } } }); @@ -632,7 +666,7 @@ App::shutdown() ->inject('user') ->inject('queueForEvents') ->inject('queueForAudits') - ->inject('queueForUsage') + ->inject('queueForStatsUsage') ->inject('queueForDeletes') ->inject('queueForDatabase') ->inject('queueForBuilds') @@ -641,9 +675,7 @@ App::shutdown() ->inject('queueForWebhooks') ->inject('queueForRealtime') ->inject('dbForProject') - ->inject('mode') - ->inject('dbForConsole') - ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Audit $queueForAudits, Usage $queueForUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject, string $mode, Database $dbForConsole) use ($parseLabel) { + ->action(function (App $utopia, Request $request, Response $response, Document $project, Document $user, Event $queueForEvents, Audit $queueForAudits, StatsUsage $queueForStatsUsage, Delete $queueForDeletes, EventDatabase $queueForDatabase, Build $queueForBuilds, Messaging $queueForMessaging, Func $queueForFunctions, Event $queueForWebhooks, Realtime $queueForRealtime, Database $dbForProject) use ($parseLabel) { $responsePayload = $response->getPayload(); @@ -652,10 +684,6 @@ App::shutdown() $queueForEvents->setPayload($responsePayload); } - $queueForWebhooks - ->from($queueForEvents) - ->trigger(); - $queueForFunctions ->from($queueForEvents) ->trigger(); @@ -665,6 +693,17 @@ App::shutdown() ->from($queueForEvents) ->trigger(); } + + /** Trigger webhooks events only if a project has them enabled + * A future optimisation is to only trigger webhooks if the webhook is "enabled" + * But it might have performance implications on the API due to the number of webhooks etc. + * Some profiling is needed to see if this is a problem. + */ + if (!empty($project->getAttribute('webhooks'))) { + $queueForWebhooks + ->from($queueForEvents) + ->trigger(); + } } $route = $utopia->getRoute(); @@ -682,10 +721,32 @@ App::shutdown() } if (!$user->isEmpty()) { + $userClone = clone $user; + // $user doesn't support `type` and can cause unintended effects. + $userClone->setAttribute('type', Auth::ACTIVITY_TYPE_USER); + $queueForAudits->setUser($userClone); + } elseif ($queueForAudits->getUser() === null || $queueForAudits->getUser()->isEmpty()) { + /** + * User in the request is empty, and no user was set for auditing previously. + * This indicates: + * - No API Key was used. + * - No active session exists. + * + * Therefore, we consider this an anonymous request and create a relevant user. + */ + $user = new Document([ + '$id' => '', + 'status' => true, + 'type' => Auth::ACTIVITY_TYPE_GUEST, + 'email' => 'guest.' . $project->getId() . '@service.' . $request->getHostname(), + 'password' => '', + 'name' => 'Guest', + ]); + $queueForAudits->setUser($user); } - if (!empty($queueForAudits->getResource()) && !empty($queueForAudits->getUser()->getId())) { + if (!empty($queueForAudits->getResource()) && !$queueForAudits->getUser()->isEmpty()) { /** * audits.payload is switched to default true * in order to auto audit payload for all endpoints @@ -698,6 +759,7 @@ App::shutdown() foreach ($queueForEvents->getParams() as $key => $value) { $queueForAudits->setParam($key, $value); } + $queueForAudits->trigger(); } @@ -717,9 +779,7 @@ App::shutdown() $queueForMessaging->trigger(); } - /** - * Cache label - */ + // Cache label $useCache = $route->getLabel('cache', false); if ($useCache) { $resource = $resourceType = null; @@ -763,8 +823,6 @@ App::shutdown() } } - - if ($project->getId() !== 'console') { if (!Auth::isPrivilegedUser(Authorization::getRoles())) { $fileSize = 0; @@ -773,43 +831,16 @@ App::shutdown() $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; } - $queueForUsage + $queueForStatsUsage ->addMetric(METRIC_NETWORK_REQUESTS, 1) ->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize) ->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize()); } - $queueForUsage + $queueForStatsUsage ->setProject($project) ->trigger(); } - - /** - * Update project last activity - */ - if (!$project->isEmpty() && $project->getId() !== 'console') { - $accessedAt = $project->getAttribute('accessedAt', ''); - if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { - $project->setAttribute('accessedAt', DateTime::now()); - Authorization::skip(fn () => $dbForConsole->updateDocument('projects', $project->getId(), $project)); - } - } - - /** - * Update user last activity - */ - if (!$user->isEmpty()) { - $accessedAt = $user->getAttribute('accessedAt', ''); - if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_USER_ACCESS)) > $accessedAt) { - $user->setAttribute('accessedAt', DateTime::now()); - - if (APP_MODE_ADMIN !== $mode) { - $dbForProject->updateDocument('users', $user->getId(), $user); - } else { - $dbForConsole->updateDocument('users', $user->getId(), $user); - } - } - } }); App::init() diff --git a/app/controllers/shared/api/auth.php b/app/controllers/shared/api/auth.php index 53aacabe21..ecabc641ec 100644 --- a/app/controllers/shared/api/auth.php +++ b/app/controllers/shared/api/auth.php @@ -5,6 +5,7 @@ use Appwrite\Extend\Exception; use Appwrite\Utopia\Request; use MaxMind\Db\Reader; use Utopia\App; +use Utopia\Config\Config; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; @@ -57,44 +58,44 @@ App::init() $auths = $project->getAttribute('auths', []); switch ($route->getLabel('auth.type', '')) { - case 'emailPassword': - if (($auths['emailPassword'] ?? true) === false) { + case 'email-password': + if (($auths[Config::getParam('auth')['email-password']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Email / Password authentication is disabled for this project'); } break; case 'magic-url': - if (($auths['usersAuthMagicURL'] ?? true) === false) { + if (($auths[Config::getParam('auth')['magic-url']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Magic URL authentication is disabled for this project'); } break; case 'anonymous': - if (($auths['anonymous'] ?? true) === false) { + if (($auths[Config::getParam('auth')['anonymous']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Anonymous authentication is disabled for this project'); } break; case 'phone': - if (($auths['phone'] ?? true) === false) { + if (($auths[Config::getParam('auth')['phone']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Phone authentication is disabled for this project'); } break; case 'invites': - if (($auths['invites'] ?? true) === false) { + if (($auths[Config::getParam('auth')['invites']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Invites authentication is disabled for this project'); } break; case 'jwt': - if (($auths['JWT'] ?? true) === false) { + if (($auths[Config::getParam('auth')['jwt']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'JWT authentication is disabled for this project'); } break; case 'email-otp': - if (($auths['emailOTP'] ?? true) === false) { + if (($auths[Config::getParam('auth')['email-otp']['key']] ?? true) === false) { throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Email OTP authentication is disabled for this project'); } break; diff --git a/app/http.php b/app/http.php index 641143694d..e4276a4dec 100644 --- a/app/http.php +++ b/app/http.php @@ -9,16 +9,19 @@ use Swoole\Http\Request as SwooleRequest; use Swoole\Http\Response as SwooleResponse; use Swoole\Http\Server; use Swoole\Process; -use Utopia\Abuse\Adapters\Database\TimeLimit; +use Swoole\Table; use Utopia\App; use Utopia\Audit\Audit; use Utopia\CLI\Console; +use Utopia\Compression\Compression; use Utopia\Config\Config; use Utopia\Database\Database; +use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Logger\Log; use Utopia\Logger\Log\User; @@ -26,6 +29,14 @@ use Utopia\Pools\Group; use Utopia\Swoole\Files; use Utopia\System\System; +Files::load(__DIR__.'/../public'); + +const DOMAIN_SYNC_TIMER = 30; // 30 seconds + +$domains = new Table(1_000_000); // 1 million rows +$domains->column('value', Table::TYPE_INT, 1); +$domains->create(); + $http = new Server( host: "0.0.0.0", port: System::getEnv('PORT', 80), @@ -33,15 +44,17 @@ $http = new Server( ); $payloadSize = 12 * (1024 * 1024); // 12MB - adding slight buffer for headers and other data that might be sent with the payload - update later with valid testing -$workerNumber = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); +$totalWorkers = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); $http ->set([ - 'worker_num' => $workerNumber, + 'worker_num' => $totalWorkers, + 'dispatch_func' => 'dispatch', 'open_http2_protocol' => true, 'http_compression' => false, 'package_max_length' => $payloadSize, 'buffer_output_size' => $payloadSize, + 'task_worker_num' => 1, // required for the task to fetch domains background ]); $http->on(Constant::EVENT_WORKER_START, function ($server, $workerId) { @@ -56,168 +69,349 @@ $http->on(Constant::EVENT_AFTER_RELOAD, function ($server, $workerId) { Console::success('Reload completed...'); }); +/** + * Assigns HTTP requests to worker threads by analyzing its payload/content. + * + * Routes requests as 'safe' or 'risky' based on specific content patterns (like POST actions or certain domains) + * to optimize load distribution between the workers. Utilizes `$safeThreadsPercent` to manage risk by assigning + * riskier tasks to a dedicated worker subset. Prefers idle workers, with fallback to random selection if necessary. + * doc: https://openswoole.com/docs/modules/swoole-server/configuration#dispatch_func + * + * @param Server $server Swoole server instance. + * @param int $fd client ID + * @param int $type the type of data and its current state + * @param string|null $data Request content for categorization. + * @global int $totalThreads Total number of workers. + * @return int Chosen worker ID for the request. + */ +function dispatch(Server $server, int $fd, int $type, $data = null): int +{ + global $totalWorkers, $domains; + + // If data is not set we can send request to any worker + // first we try to pick idle worker, if not we randomly pick a worker + if ($data === null) { + for ($i = 0; $i < $totalWorkers; $i++) { + if ($server->getWorkerStatus($i) === SWOOLE_WORKER_IDLE) { + return $i; + } + } + return rand(0, $totalWorkers - 1); + } + + $riskyWorkersPercent = intval(System::getEnv('_APP_RISKY_WORKERS_PERCENT', 80)) / 100; // Decimal form 0 to 1 + + // Each worker has numeric ID, starting from 0 and incrementing + // From 0 to riskyWorkers, we consider safe workers + // From riskyWorkers to totalWorkers, we consider risky workers + $riskyWorkers = (int) floor($totalWorkers * $riskyWorkersPercent); // Absolute amount of risky workers + + $domain = ''; + // max up to 3 as first line has request details and second line has host + $lines = explode("\n", $data, 3); + $request = $lines[0]; + if (count($lines) > 1) { + $domain = trim(explode('Host: ', $lines[1])[1]); + } + + // Sync executions are considered risky + $risky = false; + if (str_starts_with($request, 'POST') && str_contains($request, '/executions')) { + $risky = true; + } elseif (str_ends_with($domain, System::getEnv('_APP_DOMAIN_FUNCTIONS'))) { + $risky = true; + } elseif ($domains->get(md5($domain), 'value') === 1) { + // executions request coming from custom domain + $risky = true; + } + + if ($risky) { + // If risky request, only consider risky workers + for ($j = $riskyWorkers; $j < $totalWorkers; $j++) { + /** Reference https://openswoole.com/docs/modules/swoole-server-getWorkerStatus#description */ + if ($server->getWorkerStatus($j) === SWOOLE_WORKER_IDLE) { + // If idle worker found, give to him + return $j; + } + } + + // If no idle workers, give to random risky worker + $worker = rand($riskyWorkers, $totalWorkers - 1); + Console::warning("swoole_dispatch: Risky branch: did not find a idle worker, picking random worker {$worker}"); + return $worker; + } + + // If safe request, give to any idle worker + // Its fine to pick risky worker here, because it's idle. Idle is never actually risky + for ($i = 0; $i < $totalWorkers; $i++) { + if ($server->getWorkerStatus($i) === SWOOLE_WORKER_IDLE) { + return $i; + } + } + + // If no idle worker found, give to random safe worker + // We avoid risky workers here, as it could be in work - not idle. Thats exactly when they are risky. + $worker = rand(0, $riskyWorkers - 1); + Console::warning("swoole_dispatch: Non-risky branch: did not find a idle worker, picking random worker {$worker}"); + return $worker; +} + include __DIR__ . '/controllers/general.php'; +function createDatabase(App $app, string $resourceKey, string $dbName, array $collections, mixed $pools, callable $extraSetup = null): void +{ + $max = 10; + $sleep = 1; + $attempts = 0; + + do { + try { + $attempts++; + $resource = $app->getResource($resourceKey); + /* @var $database Database */ + $database = is_callable($resource) ? $resource() : $resource; + 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..."); + + // Attempt to create the database + try { + Console::info(" └── Creating database: $dbName..."); + $database->create(); + } catch (\Exception $e) { + Console::info(" └── Skip: metadata table already exists"); + } + + // Process collections + foreach ($collections as $key => $collection) { + if (($collection['$collection'] ?? '') !== Database::METADATA) { + continue; + } + + if (!$database->getCollection($key)->isEmpty()) { + continue; + } + + Console::info(" └── Creating collection: {$collection['$id']}..."); + + $attributes = array_map(fn ($attr) => new Document([ + '$id' => ID::custom($attr['$id']), + 'type' => $attr['type'], + 'size' => $attr['size'], + 'required' => $attr['required'], + 'signed' => $attr['signed'], + 'array' => $attr['array'], + 'filters' => $attr['filters'], + 'default' => $attr['default'] ?? null, + 'format' => $attr['format'] ?? '' + ]), $collection['attributes']); + + $indexes = array_map(fn ($index) => new Document([ + '$id' => ID::custom($index['$id']), + 'type' => $index['type'], + 'attributes' => $index['attributes'], + 'lengths' => $index['lengths'], + 'orders' => $index['orders'], + ]), $collection['indexes']); + + $database->createCollection($key, $attributes, $indexes); + } + + if ($extraSetup) { + $extraSetup($database); + } +} + $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $register) { $app = new App('UTC'); - $app->setCompression(true); - $app->setCompressionMinSize(intval(System::getEnv('_APP_COMPRESSION_MIN_SIZE_BYTES', '1024'))); // 1KB go(function () use ($register, $app) { $pools = $register->get('pools'); /** @var Group $pools */ App::setResource('pools', fn () => $pools); - // wait for database to be ready - $attempts = 0; - $max = 10; - $sleep = 1; - - do { - try { - $attempts++; - $dbForConsole = $app->getResource('dbForConsole'); - /** @var Utopia\Database\Database $dbForConsole */ - break; // leave the do-while if successful - } catch (\Throwable $e) { - Console::warning("Database not ready. Retrying connection ({$attempts})..."); - if ($attempts >= $max) { - throw new \Exception('Failed to connect to database: ' . $e->getMessage()); - } - sleep($sleep); - } - } while ($attempts < $max); - - Console::success('[Setup] - Server database init started...'); - - try { - Console::success('[Setup] - Creating database: appwrite...'); - $dbForConsole->create(); - } catch (\Throwable $e) { - Console::success('[Setup] - Skip: metadata table already exists'); - } - - if ($dbForConsole->getCollection(Audit::COLLECTION)->isEmpty()) { - $audit = new Audit($dbForConsole); - $audit->setup(); - } - - if ($dbForConsole->getCollection(TimeLimit::COLLECTION)->isEmpty()) { - $adapter = new TimeLimit("", 0, 1, $dbForConsole); - $adapter->setup(); - } - /** @var array $collections */ $collections = Config::getParam('collections', []); - $consoleCollections = $collections['console']; - foreach ($consoleCollections as $key => $collection) { - if (($collection['$collection'] ?? '') !== Database::METADATA) { - continue; - } - if (!$dbForConsole->getCollection($key)->isEmpty()) { - continue; + + // create logs database first, `getLogsDB` is a callable. + createDatabase($app, 'getLogsDB', 'logs', $collections['logs'], $pools); + + // create appwrite database, `dbForPlatform` is a direct access call. + createDatabase($app, 'dbForPlatform', 'appwrite', $collections['console'], $pools, function (Database $dbForPlatform) use ($collections) { + if ($dbForPlatform->getCollection(Audit::COLLECTION)->isEmpty()) { + $audit = new Audit($dbForPlatform); + $audit->setup(); } - Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...'); + if ($dbForPlatform->getDocument('buckets', 'default')->isEmpty()) { + Console::info(" └── Creating default bucket..."); + $dbForPlatform->createDocument('buckets', new Document([ + '$id' => ID::custom('default'), + '$collection' => ID::custom('buckets'), + 'name' => 'Default', + 'maximumFileSize' => (int) System::getEnv('_APP_STORAGE_LIMIT', 0), + 'allowedFileExtensions' => [], + 'enabled' => true, + 'compression' => 'gzip', + 'encryption' => true, + 'antivirus' => true, + 'fileSecurity' => true, + '$permissions' => [ + Permission::create(Role::any()), + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'search' => 'buckets Default', + ])); - $attributes = []; - $indexes = []; + $bucket = $dbForPlatform->getDocument('buckets', 'default'); - foreach ($collection['attributes'] as $attribute) { - $attributes[] = new Document([ - '$id' => ID::custom($attribute['$id']), - 'type' => $attribute['type'], - 'size' => $attribute['size'], - 'required' => $attribute['required'], - 'signed' => $attribute['signed'], - 'array' => $attribute['array'], - 'filters' => $attribute['filters'], - 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' - ]); - } + Console::info(" └── Creating files collection for default bucket..."); + $files = $collections['buckets']['files'] ?? []; + if (empty($files)) { + throw new Exception('Files collection is not configured.'); + } - foreach ($collection['indexes'] as $index) { - $indexes[] = new Document([ + $attributes = array_map(fn ($attr) => new Document([ + '$id' => ID::custom($attr['$id']), + 'type' => $attr['type'], + 'size' => $attr['size'], + 'required' => $attr['required'], + 'signed' => $attr['signed'], + 'array' => $attr['array'], + 'filters' => $attr['filters'], + 'default' => $attr['default'] ?? null, + 'format' => $attr['format'] ?? '' + ]), $files['attributes']); + + $indexes = array_map(fn ($index) => new Document([ '$id' => ID::custom($index['$id']), 'type' => $index['type'], 'attributes' => $index['attributes'], 'lengths' => $index['lengths'], 'orders' => $index['orders'], - ]); + ]), $files['indexes']); + + $dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); } - $dbForConsole->createCollection($key, $attributes, $indexes); - } + if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { + Console::info(" └── Creating screenshots bucket..."); + Authorization::skip(fn () => $dbForPlatform->createDocument('buckets', new Document([ + '$id' => ID::custom('screenshots'), + '$collection' => ID::custom('buckets'), + 'name' => 'Screenshots', + 'maximumFileSize' => 5000000, // ~5MB + 'allowedFileExtensions' => [ 'png' ], + 'enabled' => true, + 'compression' => Compression::GZIP, + 'encryption' => false, + 'antivirus' => false, + 'fileSecurity' => true, + '$permissions' => [], + 'search' => 'buckets Screenshots', + ]))); - if ($dbForConsole->getDocument('buckets', 'default')->isEmpty() && !$dbForConsole->exists($dbForConsole->getDatabase(), 'bucket_1')) { - Console::success('[Setup] - Creating default bucket...'); - $dbForConsole->createDocument('buckets', new Document([ - '$id' => ID::custom('default'), - '$collection' => ID::custom('buckets'), - 'name' => 'Default', - 'maximumFileSize' => (int) System::getEnv('_APP_STORAGE_LIMIT', 0), // 10MB - 'allowedFileExtensions' => [], - 'enabled' => true, - 'compression' => 'gzip', - 'encryption' => true, - 'antivirus' => true, - 'fileSecurity' => true, - '$permissions' => [ - Permission::create(Role::any()), - Permission::read(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], - 'search' => 'buckets Default', - ])); + $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); - $bucket = $dbForConsole->getDocument('buckets', 'default'); + Console::info(" └── Creating files collection for screenshots bucket..."); + $files = $collections['buckets']['files'] ?? []; + if (empty($files)) { + throw new Exception('Files collection is not configured.'); + } - Console::success('[Setup] - Creating files collection for default bucket...'); - $files = $collections['buckets']['files'] ?? []; - if (empty($files)) { - throw new Exception('Files collection is not configured.'); - } + $attributes = array_map(fn ($attr) => new Document([ + '$id' => ID::custom($attr['$id']), + 'type' => $attr['type'], + 'size' => $attr['size'], + 'required' => $attr['required'], + 'signed' => $attr['signed'], + 'array' => $attr['array'], + 'filters' => $attr['filters'], + 'default' => $attr['default'] ?? null, + 'format' => $attr['format'] ?? '' + ]), $files['attributes']); - $attributes = []; - $indexes = []; - - foreach ($files['attributes'] as $attribute) { - $attributes[] = new Document([ - '$id' => ID::custom($attribute['$id']), - 'type' => $attribute['type'], - 'size' => $attribute['size'], - 'required' => $attribute['required'], - 'signed' => $attribute['signed'], - 'array' => $attribute['array'], - 'filters' => $attribute['filters'], - 'default' => $attribute['default'] ?? null, - 'format' => $attribute['format'] ?? '' - ]); - } - - foreach ($files['indexes'] as $index) { - $indexes[] = new Document([ + $indexes = array_map(fn ($index) => new Document([ '$id' => ID::custom($index['$id']), 'type' => $index['type'], 'attributes' => $index['attributes'], 'lengths' => $index['lengths'], 'orders' => $index['orders'], - ]); + ]), $files['indexes']); + + Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes)); + } + }); + + $projectCollections = $collections['projects']; + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + $sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', '')); + $sharedTablesV2 = \array_diff($sharedTables, $sharedTablesV1); + + $cache = $app->getResource('cache'); + + foreach ($sharedTablesV2 as $hostname) { + $adapter = $pools + ->get($hostname) + ->pop() + ->getResource(); + + $dbForProject = (new Database($adapter, $cache)) + ->setDatabase('appwrite') + ->setSharedTables(true) + ->setTenant(null) + ->setNamespace(System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + + try { + Console::success('[Setup] - Creating project database: ' . $hostname . '...'); + $dbForProject->create(); + } catch (Duplicate) { + Console::success('[Setup] - Skip: metadata table already exists'); } - $dbForConsole->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); + if ($dbForProject->getCollection(Audit::COLLECTION)->isEmpty()) { + $audit = new Audit($dbForProject); + $audit->setup(); + } + + foreach ($projectCollections as $key => $collection) { + if (($collection['$collection'] ?? '') !== Database::METADATA) { + continue; + } + if (!$dbForProject->getCollection($key)->isEmpty()) { + continue; + } + + $attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']); + $indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']); + + Console::success('[Setup] - Creating project collection: ' . $collection['$id'] . '...'); + + $dbForProject->createCollection($key, $attributes, $indexes); + } } $pools->reclaim(); - Console::success('[Setup] - Server database init completed...'); }); Console::success('Server started successfully (max payload is ' . number_format($payloadSize) . ' bytes)'); Console::info("Master pid {$http->master_pid}, manager pid {$http->manager_pid}"); + // Start the task that starts fetching custom domains + $http->task([], 0); + // listen ctrl + c Process::signal(2, function () use ($http) { Console::log('Stop by Ctrl+C'); @@ -225,7 +419,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg }); }); -$http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register) { +$http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register) { App::setResource('swooleRequest', fn () => $swooleRequest); App::setResource('swooleResponse', fn () => $swooleResponse); @@ -245,7 +439,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo } $app = new App('UTC'); - $app->setCompression(true); + $app->setCompression(System::getEnv('_APP_COMPRESSION_ENABLED', 'enabled') === 'enabled'); $app->setCompressionMinSize(intval(System::getEnv('_APP_COMPRESSION_MIN_SIZE_BYTES', '1024'))); // 1KB $pools = $register->get('pools'); @@ -274,10 +468,12 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo if (isset($user) && !$user->isEmpty()) { $log->setUser(new User($user->getId())); + } else { + $log->setUser(new User('guest-' . hash('sha256', $request->getIP()))); } $log->setNamespace("http"); - $log->setServer(\gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($th->getMessage()); @@ -295,8 +491,16 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo $log->addExtra('trace', $th->getTraceAsString()); $log->addExtra('roles', Authorization::getRoles()); - $action = $route->getLabel("sdk.namespace", "UNKNOWN_NAMESPACE") . '.' . $route->getLabel("sdk.method", "UNKNOWN_METHOD"); + $sdk = $route->getLabel("sdk", false); + + $action = 'UNKNOWN_NAMESPACE.UNKNOWN.METHOD'; + if (!empty($sdk)) { + /** @var Appwrite\SDK\Method $sdk */ + $action = $sdk->getNamespace() . '.' . $sdk->getMethodName(); + } + $log->setAction($action); + $log->addTag('service', $action); $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); @@ -335,4 +539,58 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo } }); +// Fetch domains every `DOMAIN_SYNC_TIMER` seconds and update in the memory +$http->on('Task', function () use ($register, $domains) { + $lastSyncUpdate = null; + $pools = $register->get('pools'); + App::setResource('pools', fn () => $pools); + $app = new App('UTC'); + + /** @var Utopia\Database\Database $dbForPlatform */ + $dbForPlatform = $app->getResource('dbForPlatform'); + + Console::loop(function () use ($dbForPlatform, $domains, &$lastSyncUpdate) { + try { + $time = DateTime::now(); + $limit = 1000; + $sum = $limit; + $latestDocument = null; + + while ($sum === $limit) { + $queries = [Query::limit($limit)]; + if ($latestDocument !== null) { + $queries[] = Query::cursorAfter($latestDocument); + } + if ($lastSyncUpdate != null) { + $queries[] = Query::greaterThanEqual('$updatedAt', $lastSyncUpdate); + } + $results = []; + try { + $results = Authorization::skip(fn () => $dbForPlatform->find('rules', $queries)); + } catch (Throwable $th) { + Console::error($th->getMessage()); + } + + $sum = count($results); + foreach ($results as $document) { + $domain = $document->getAttribute('domain'); + if (str_ends_with($domain, System::getEnv('_APP_DOMAIN_FUNCTIONS')) || str_ends_with($domain, System::getEnv('_APP_DOMAIN_SITES'))) { + continue; + } + $domains->set(md5($domain), ['value' => 1]); + } + $latestDocument = !empty(array_key_last($results)) ? $results[array_key_last($results)] : null; + } + $lastSyncUpdate = $time; + if ($sum > 0) { + Console::log("Sync domains tick: {$sum} domains were updated"); + } + } catch (Throwable $th) { + Console::error($th->getMessage()); + } + }, DOMAIN_SYNC_TIMER, 0, function ($error) { + Console::error($error); + }); +}); + $http->start(); diff --git a/app/init.php b/app/init.php index c9ec2e0061..c32f1eb9a8 100644 --- a/app/init.php +++ b/app/init.php @@ -8,6 +8,8 @@ * */ +use Utopia\System\System; + if (\file_exists(__DIR__ . '/../vendor/autoload.php')) { require_once __DIR__ . '/../vendor/autoload.php'; } @@ -18,1076 +20,13 @@ if (\file_exists(__DIR__ . '/../vendor/autoload.php')) { \ini_set('default_socket_timeout', -1); \error_reporting(E_ALL); -use Ahc\Jwt\JWT; -use Ahc\Jwt\JWTException; -use Appwrite\Auth\Auth; -use Appwrite\Event\Audit; -use Appwrite\Event\Build; -use Appwrite\Event\Certificate; -use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Delete; -use Appwrite\Event\Event; -use Appwrite\Event\Func; -use Appwrite\Event\Mail; -use Appwrite\Event\Messaging; -use Appwrite\Event\Migration; -use Appwrite\Event\Realtime; -use Appwrite\Event\Usage; -use Appwrite\Event\Webhook; -use Appwrite\Extend\Exception; -use Appwrite\Functions\Specification; -use Appwrite\GraphQL\Promises\Adapter\Swoole; -use Appwrite\GraphQL\Schema; -use Appwrite\Hooks\Hooks; -use Appwrite\Network\Validator\Email; -use Appwrite\Network\Validator\Origin; -use Appwrite\OpenSSL\OpenSSL; -use Appwrite\PubSub\Adapter\Redis as PubSub; -use Appwrite\URL\URL as AppwriteURL; -use Appwrite\Utopia\Request; -use MaxMind\Db\Reader; -use PHPMailer\PHPMailer\PHPMailer; -use Swoole\Database\PDOProxy; -use Utopia\App; -use Utopia\Cache\Adapter\Redis as RedisCache; -use Utopia\Cache\Adapter\Sharding; -use Utopia\Cache\Cache; -use Utopia\CLI\Console; -use Utopia\Config\Config; -use Utopia\Database\Adapter\MariaDB; -use Utopia\Database\Adapter\MySQL; -use Utopia\Database\Adapter\SQL; -use Utopia\Database\Database; -use Utopia\Database\Document; -use Utopia\Database\Helpers\ID; -use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; -use Utopia\Database\Validator\Datetime as DatetimeValidator; -use Utopia\Database\Validator\Structure; -use Utopia\Domains\Validator\PublicDomain; -use Utopia\DSN\DSN; -use Utopia\Locale\Locale; -use Utopia\Logger\Adapter\AppSignal; -use Utopia\Logger\Adapter\LogOwl; -use Utopia\Logger\Adapter\Raygun; -use Utopia\Logger\Adapter\Sentry; -use Utopia\Logger\Log; -use Utopia\Logger\Logger; -use Utopia\Pools\Group; -use Utopia\Pools\Pool; -use Utopia\Queue; -use Utopia\Queue\Connection; -use Utopia\Registry\Registry; -use Utopia\Storage\Device; -use Utopia\Storage\Device\Backblaze; -use Utopia\Storage\Device\DOSpaces; -use Utopia\Storage\Device\Linode; -use Utopia\Storage\Device\Local; -use Utopia\Storage\Device\S3; -use Utopia\Storage\Device\Wasabi; -use Utopia\Storage\Storage; -use Utopia\System\System; -use Utopia\Validator\Hostname; -use Utopia\Validator\IP; -use Utopia\Validator\Range; -use Utopia\Validator\URL; -use Utopia\Validator\WhiteList; -use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub; - -const APP_NAME = 'Appwrite'; -const APP_DOMAIN = 'appwrite.io'; -const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address -const APP_EMAIL_SECURITY = ''; // Default security email address -const APP_USERAGENT = APP_NAME . '-Server v%s. Please report abuse at %s'; -const APP_MODE_DEFAULT = 'default'; -const APP_MODE_ADMIN = 'admin'; -const APP_PAGING_LIMIT = 12; -const APP_LIMIT_COUNT = 5000; -const APP_LIMIT_USERS = 10_000; -const APP_LIMIT_USER_PASSWORD_HISTORY = 20; -const APP_LIMIT_USER_SESSIONS_MAX = 100; -const APP_LIMIT_USER_SESSIONS_DEFAULT = 10; -const APP_LIMIT_ANTIVIRUS = 20_000_000; //20MB -const APP_LIMIT_ENCRYPTION = 20_000_000; //20MB -const APP_LIMIT_COMPRESSION = 20_000_000; //20MB -const APP_LIMIT_ARRAY_PARAMS_SIZE = 100; // Default maximum of how many elements can there be in API parameter that expects array value -const APP_LIMIT_ARRAY_LABELS_SIZE = 1000; // Default maximum of how many labels elements can there be in API parameter that expects array value -const APP_LIMIT_ARRAY_ELEMENT_SIZE = 4096; // Default maximum length of element in array parameter represented by maximum URL length. -const APP_LIMIT_SUBQUERY = 1000; -const APP_LIMIT_SUBSCRIBERS_SUBQUERY = 1_000_000; -const APP_LIMIT_WRITE_RATE_DEFAULT = 60; // Default maximum write rate per rate period -const APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT = 60; // Default maximum write rate period in seconds -const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return in list API calls -const APP_KEY_ACCESS = 24 * 60 * 60; // 24 hours -const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours -const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours -const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours -const APP_CACHE_BUSTER = 4318; -const APP_VERSION_STABLE = '1.6.0'; -const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; -const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; -const APP_DATABASE_ATTRIBUTE_IP = 'ip'; -const APP_DATABASE_ATTRIBUTE_DATETIME = 'datetime'; -const APP_DATABASE_ATTRIBUTE_URL = 'url'; -const APP_DATABASE_ATTRIBUTE_INT_RANGE = 'intRange'; -const APP_DATABASE_ATTRIBUTE_FLOAT_RANGE = 'floatRange'; -const APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH = 1_073_741_824; // 2^32 bits / 4 bits per char -const APP_DATABASE_TIMEOUT_MILLISECONDS = 15_000; -const APP_DATABASE_QUERY_MAX_VALUES = 500; -const APP_STORAGE_UPLOADS = '/storage/uploads'; -const APP_STORAGE_FUNCTIONS = '/storage/functions'; -const APP_STORAGE_BUILDS = '/storage/builds'; -const APP_STORAGE_CACHE = '/storage/cache'; -const APP_STORAGE_CERTIFICATES = '/storage/certificates'; -const APP_STORAGE_CONFIG = '/storage/config'; -const APP_STORAGE_READ_BUFFER = 20 * (1000 * 1000); //20MB other names `APP_STORAGE_MEMORY_LIMIT`, `APP_STORAGE_MEMORY_BUFFER`, `APP_STORAGE_READ_LIMIT`, `APP_STORAGE_BUFFER_LIMIT` -const APP_SOCIAL_TWITTER = 'https://twitter.com/appwrite'; -const APP_SOCIAL_TWITTER_HANDLE = 'appwrite'; -const APP_SOCIAL_FACEBOOK = 'https://www.facebook.com/appwrite.io'; -const APP_SOCIAL_LINKEDIN = 'https://www.linkedin.com/company/appwrite'; -const APP_SOCIAL_INSTAGRAM = 'https://www.instagram.com/appwrite.io'; -const APP_SOCIAL_GITHUB = 'https://github.com/appwrite'; -const APP_SOCIAL_DISCORD = 'https://appwrite.io/discord'; -const APP_SOCIAL_DISCORD_CHANNEL = '564160730845151244'; -const APP_SOCIAL_DEV = 'https://dev.to/appwrite'; -const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite'; -const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation=1'; -const APP_HOSTNAME_INTERNAL = 'appwrite'; -const APP_FUNCTION_SPECIFICATION_DEFAULT = Specification::S_1VCPU_512MB; -const APP_FUNCTION_CPUS_DEFAULT = 0.5; -const APP_FUNCTION_MEMORY_DEFAULT = 512; -const APP_PLATFORM_SERVER = 'server'; -const APP_PLATFORM_CLIENT = 'client'; -const APP_PLATFORM_CONSOLE = 'console'; - -// Database Reconnect -const DATABASE_RECONNECT_SLEEP = 2; -const DATABASE_RECONNECT_MAX_ATTEMPTS = 10; - -// Database Worker Types -const DATABASE_TYPE_CREATE_ATTRIBUTE = 'createAttribute'; -const DATABASE_TYPE_CREATE_INDEX = 'createIndex'; -const DATABASE_TYPE_DELETE_ATTRIBUTE = 'deleteAttribute'; -const DATABASE_TYPE_DELETE_INDEX = 'deleteIndex'; -const DATABASE_TYPE_DELETE_COLLECTION = 'deleteCollection'; -const DATABASE_TYPE_DELETE_DATABASE = 'deleteDatabase'; - -// Build Worker Types -const BUILD_TYPE_DEPLOYMENT = 'deployment'; -const BUILD_TYPE_RETRY = 'retry'; - -// Deletion Types -const DELETE_TYPE_DATABASES = 'databases'; -const DELETE_TYPE_DOCUMENT = 'document'; -const DELETE_TYPE_COLLECTIONS = 'collections'; -const DELETE_TYPE_PROJECTS = 'projects'; -const DELETE_TYPE_FUNCTIONS = 'functions'; -const DELETE_TYPE_DEPLOYMENTS = 'deployments'; -const DELETE_TYPE_USERS = 'users'; -const DELETE_TYPE_TEAM_PROJECTS = 'teams_projects'; -const DELETE_TYPE_EXECUTIONS = 'executions'; -const DELETE_TYPE_AUDIT = 'audit'; -const DELETE_TYPE_ABUSE = 'abuse'; -const DELETE_TYPE_USAGE = 'usage'; -const DELETE_TYPE_REALTIME = 'realtime'; -const DELETE_TYPE_BUCKETS = 'buckets'; -const DELETE_TYPE_INSTALLATIONS = 'installations'; -const DELETE_TYPE_RULES = 'rules'; -const DELETE_TYPE_SESSIONS = 'sessions'; -const DELETE_TYPE_CACHE_BY_TIMESTAMP = 'cacheByTimeStamp'; -const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource'; -const DELETE_TYPE_SCHEDULES = 'schedules'; -const DELETE_TYPE_TOPIC = 'topic'; -const DELETE_TYPE_TARGET = 'target'; -const DELETE_TYPE_EXPIRED_TARGETS = 'invalid_targets'; -const DELETE_TYPE_SESSION_TARGETS = 'session_targets'; - -// Message types -const MESSAGE_SEND_TYPE_INTERNAL = 'internal'; -const MESSAGE_SEND_TYPE_EXTERNAL = 'external'; -// Mail Types -const MAIL_TYPE_VERIFICATION = 'verification'; -const MAIL_TYPE_MAGIC_SESSION = 'magicSession'; -const MAIL_TYPE_RECOVERY = 'recovery'; -const MAIL_TYPE_INVITATION = 'invitation'; -const MAIL_TYPE_CERTIFICATE = 'certificate'; -// Auth Types -const APP_AUTH_TYPE_SESSION = 'Session'; -const APP_AUTH_TYPE_JWT = 'JWT'; -const APP_AUTH_TYPE_KEY = 'Key'; -const APP_AUTH_TYPE_ADMIN = 'Admin'; -// Response related -const MAX_OUTPUT_CHUNK_SIZE = 10 * 1024 * 1024; // 10MB -// Function headers -const FUNCTION_ALLOWLIST_HEADERS_REQUEST = ['content-type', 'agent', 'content-length', 'host']; -const FUNCTION_ALLOWLIST_HEADERS_RESPONSE = ['content-type', 'content-length']; -// Message types -const MESSAGE_TYPE_EMAIL = 'email'; -const MESSAGE_TYPE_SMS = 'sms'; -const MESSAGE_TYPE_PUSH = 'push'; -// API key types -const API_KEY_STANDARD = 'standard'; -const API_KEY_DYNAMIC = 'dynamic'; -// Usage metrics -const METRIC_TEAMS = 'teams'; -const METRIC_USERS = 'users'; - -const METRIC_AUTH_METHOD_PHONE = 'auth.method.phone'; -const METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE = METRIC_AUTH_METHOD_PHONE . '.{countryCode}'; -const METRIC_MESSAGES = 'messages'; -const METRIC_MESSAGES_SENT = METRIC_MESSAGES . '.sent'; -const METRIC_MESSAGES_FAILED = METRIC_MESSAGES . '.failed'; -const METRIC_MESSAGES_TYPE = METRIC_MESSAGES . '.{type}'; -const METRIC_MESSAGES_TYPE_SENT = METRIC_MESSAGES . '.{type}.sent'; -const METRIC_MESSAGES_TYPE_FAILED = METRIC_MESSAGES . '.{type}.failed'; -const METRIC_MESSAGES_TYPE_PROVIDER = METRIC_MESSAGES . '.{type}.{provider}'; -const METRIC_MESSAGES_TYPE_PROVIDER_SENT = METRIC_MESSAGES . '.{type}.{provider}.sent'; -const METRIC_MESSAGES_TYPE_PROVIDER_FAILED = METRIC_MESSAGES . '.{type}.{provider}.failed'; -const METRIC_SESSIONS = 'sessions'; -const METRIC_DATABASES = 'databases'; -const METRIC_COLLECTIONS = 'collections'; -const METRIC_DATABASES_STORAGE = 'databases.storage'; -const METRIC_DATABASE_ID_COLLECTIONS = '{databaseInternalId}.collections'; -const METRIC_DATABASE_ID_STORAGE = '{databaseInternalId}.databases.storage'; -const METRIC_DOCUMENTS = 'documents'; -const METRIC_DATABASE_ID_DOCUMENTS = '{databaseInternalId}.documents'; -const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collectionInternalId}.documents'; -const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE = '{databaseInternalId}.{collectionInternalId}.databases.storage'; -const METRIC_BUCKETS = 'buckets'; -const METRIC_FILES = 'files'; -const METRIC_FILES_STORAGE = 'files.storage'; -const METRIC_BUCKET_ID_FILES = '{bucketInternalId}.files'; -const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage'; -const METRIC_FUNCTIONS = 'functions'; -const METRIC_DEPLOYMENTS = 'deployments'; -const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage'; -const METRIC_BUILDS = 'builds'; -const METRIC_BUILDS_SUCCESS = 'builds.success'; -const METRIC_BUILDS_FAILED = 'builds.failed'; -const METRIC_BUILDS_STORAGE = 'builds.storage'; -const METRIC_BUILDS_COMPUTE = 'builds.compute'; -const METRIC_BUILDS_COMPUTE_SUCCESS = 'builds.compute.success'; -const METRIC_BUILDS_COMPUTE_FAILED = 'builds.compute.failed'; -const METRIC_BUILDS_MB_SECONDS = 'builds.mbSeconds'; -const METRIC_FUNCTION_ID_BUILDS = '{functionInternalId}.builds'; -const METRIC_FUNCTION_ID_BUILDS_SUCCESS = '{functionInternalId}.builds.success'; -const METRIC_FUNCTION_ID_BUILDS_FAILED = '{functionInternalId}.builds.failed'; -const METRIC_FUNCTION_ID_BUILDS_STORAGE = '{functionInternalId}.builds.storage'; -const METRIC_FUNCTION_ID_BUILDS_COMPUTE = '{functionInternalId}.builds.compute'; -const METRIC_FUNCTION_ID_BUILDS_COMPUTE_SUCCESS = '{functionInternalId}.builds.compute.success'; -const METRIC_FUNCTION_ID_BUILDS_COMPUTE_FAILED = '{functionInternalId}.builds.compute.failed'; -const METRIC_FUNCTION_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; -const METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; -const METRIC_FUNCTION_ID_BUILDS_MB_SECONDS = '{functionInternalId}.builds.mbSeconds'; -const METRIC_EXECUTIONS = 'executions'; -const METRIC_EXECUTIONS_COMPUTE = 'executions.compute'; -const METRIC_EXECUTIONS_MB_SECONDS = 'executions.mbSeconds'; -const METRIC_FUNCTION_ID_EXECUTIONS = '{functionInternalId}.executions'; -const METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE = '{functionInternalId}.executions.compute'; -const METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS = '{functionInternalId}.executions.mbSeconds'; -const METRIC_NETWORK_REQUESTS = 'network.requests'; -const METRIC_NETWORK_INBOUND = 'network.inbound'; -const METRIC_NETWORK_OUTBOUND = 'network.outbound'; - -// Resource types - -const RESOURCE_TYPE_PROJECTS = 'projects'; -const RESOURCE_TYPE_FUNCTIONS = 'functions'; -const RESOURCE_TYPE_DATABASES = 'databases'; -const RESOURCE_TYPE_BUCKETS = 'buckets'; -const RESOURCE_TYPE_PROVIDERS = 'providers'; -const RESOURCE_TYPE_TOPICS = 'topics'; -const RESOURCE_TYPE_SUBSCRIBERS = 'subscribers'; -const RESOURCE_TYPE_MESSAGES = 'messages'; - -$register = new Registry(); - -App::setMode(System::getEnv('_APP_ENV', App::MODE_TYPE_PRODUCTION)); - -if (!App::isProduction()) { - // Allow specific domains to skip public domain validation in dev environment - // Useful for existing tests involving webhooks - PublicDomain::allow(['request-catcher']); -} - -/* - * ENV vars - */ -Config::load('events', __DIR__ . '/config/events.php'); -Config::load('auth', __DIR__ . '/config/auth.php'); -Config::load('apis', __DIR__ . '/config/apis.php'); // List of APIs -Config::load('errors', __DIR__ . '/config/errors.php'); -Config::load('oAuthProviders', __DIR__ . '/config/oAuthProviders.php'); -Config::load('platforms', __DIR__ . '/config/platforms.php'); -Config::load('collections', __DIR__ . '/config/collections.php'); -Config::load('runtimes', __DIR__ . '/config/runtimes.php'); -Config::load('runtimes-v2', __DIR__ . '/config/runtimes-v2.php'); -Config::load('usage', __DIR__ . '/config/usage.php'); -Config::load('roles', __DIR__ . '/config/roles.php'); // User roles and scopes -Config::load('scopes', __DIR__ . '/config/scopes.php'); // User roles and scopes -Config::load('services', __DIR__ . '/config/services.php'); // List of services -Config::load('variables', __DIR__ . '/config/variables.php'); // List of env variables -Config::load('regions', __DIR__ . '/config/regions.php'); // List of available regions -Config::load('avatar-browsers', __DIR__ . '/config/avatars/browsers.php'); -Config::load('avatar-credit-cards', __DIR__ . '/config/avatars/credit-cards.php'); -Config::load('avatar-flags', __DIR__ . '/config/avatars/flags.php'); -Config::load('locale-codes', __DIR__ . '/config/locale/codes.php'); -Config::load('locale-currencies', __DIR__ . '/config/locale/currencies.php'); -Config::load('locale-eu', __DIR__ . '/config/locale/eu.php'); -Config::load('locale-languages', __DIR__ . '/config/locale/languages.php'); -Config::load('locale-phones', __DIR__ . '/config/locale/phones.php'); -Config::load('locale-countries', __DIR__ . '/config/locale/countries.php'); -Config::load('locale-continents', __DIR__ . '/config/locale/continents.php'); -Config::load('locale-templates', __DIR__ . '/config/locale/templates.php'); -Config::load('storage-logos', __DIR__ . '/config/storage/logos.php'); -Config::load('storage-mimes', __DIR__ . '/config/storage/mimes.php'); -Config::load('storage-inputs', __DIR__ . '/config/storage/inputs.php'); -Config::load('storage-outputs', __DIR__ . '/config/storage/outputs.php'); -Config::load('runtime-specifications', __DIR__ . '/config/runtimes/specifications.php'); -Config::load('function-templates', __DIR__ . '/config/function-templates.php'); - -/** - * New DB Filters - */ -Database::addFilter( - 'casting', - function (mixed $value) { - return json_encode(['value' => $value], JSON_PRESERVE_ZERO_FRACTION); - }, - function (mixed $value) { - if (is_null($value)) { - return; - } - - return json_decode($value, true)['value']; - } -); - -Database::addFilter( - 'enum', - function (mixed $value, Document $attribute) { - if ($attribute->isSet('elements')) { - $attribute->removeAttribute('elements'); - } - - return $value; - }, - function (mixed $value, Document $attribute) { - $formatOptions = \json_decode($attribute->getAttribute('formatOptions', '[]'), true); - if (isset($formatOptions['elements'])) { - $attribute->setAttribute('elements', $formatOptions['elements']); - } - - return $value; - } -); - -Database::addFilter( - 'range', - function (mixed $value, Document $attribute) { - if ($attribute->isSet('min')) { - $attribute->removeAttribute('min'); - } - if ($attribute->isSet('max')) { - $attribute->removeAttribute('max'); - } - - return $value; - }, - function (mixed $value, Document $attribute) { - $formatOptions = json_decode($attribute->getAttribute('formatOptions', '[]'), true); - if (isset($formatOptions['min']) || isset($formatOptions['max'])) { - $attribute - ->setAttribute('min', $formatOptions['min']) - ->setAttribute('max', $formatOptions['max']); - } - - return $value; - } -); - -Database::addFilter( - 'subQueryAttributes', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - $attributes = $database->find('attributes', [ - Query::equal('collectionInternalId', [$document->getInternalId()]), - Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), - Query::limit($database->getLimitForAttributes()), - ]); - - 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'); - } - } - - return $attributes; - } -); - -Database::addFilter( - 'subQueryIndexes', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return $database - ->find('indexes', [ - Query::equal('collectionInternalId', [$document->getInternalId()]), - Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), - Query::limit($database->getLimitForIndexes()), - ]); - } -); - -Database::addFilter( - 'subQueryPlatforms', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return $database - ->find('platforms', [ - Query::equal('projectInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), - ]); - } -); - -Database::addFilter( - 'subQueryKeys', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return $database - ->find('keys', [ - Query::equal('projectInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), - ]); - } -); - -Database::addFilter( - 'subQueryWebhooks', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return $database - ->find('webhooks', [ - Query::equal('projectInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), - ]); - } -); - -Database::addFilter( - 'subQuerySessions', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database->find('sessions', [ - Query::equal('userInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), - ])); - } -); - -Database::addFilter( - 'subQueryTokens', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database - ->find('tokens', [ - Query::equal('userInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), - ])); - } -); - -Database::addFilter( - 'subQueryChallenges', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database - ->find('challenges', [ - Query::equal('userInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), - ])); - } -); - -Database::addFilter( - 'subQueryAuthenticators', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database - ->find('authenticators', [ - Query::equal('userInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), - ])); - } -); - -Database::addFilter( - 'subQueryMemberships', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database - ->find('memberships', [ - Query::equal('userInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY), - ])); - } -); - -Database::addFilter( - 'subQueryVariables', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return $database - ->find('variables', [ - Query::equal('resourceInternalId', [$document->getInternalId()]), - Query::equal('resourceType', ['function']), - Query::limit(APP_LIMIT_SUBQUERY), - ]); - } -); - -Database::addFilter( - 'encrypt', - function (mixed $value) { - $key = System::getEnv('_APP_OPENSSL_KEY_V1'); - $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); - $tag = null; - - return json_encode([ - 'data' => OpenSSL::encrypt($value, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), - 'method' => OpenSSL::CIPHER_AES_128_GCM, - 'iv' => \bin2hex($iv), - 'tag' => \bin2hex($tag ?? ''), - 'version' => '1', - ]); - }, - function (mixed $value) { - if (is_null($value)) { - return; - } - $value = json_decode($value, true); - $key = System::getEnv('_APP_OPENSSL_KEY_V' . $value['version']); - - return OpenSSL::decrypt($value['data'], $value['method'], $key, 0, hex2bin($value['iv']), hex2bin($value['tag'])); - } -); - -Database::addFilter( - 'subQueryProjectVariables', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return $database - ->find('variables', [ - Query::equal('resourceType', ['project']), - Query::limit(APP_LIMIT_SUBQUERY) - ]); - } -); - -Database::addFilter( - 'userSearch', - function (mixed $value, Document $user) { - $searchValues = [ - $user->getId(), - $user->getAttribute('email', ''), - $user->getAttribute('name', ''), - $user->getAttribute('phone', '') - ]; - - foreach ($user->getAttribute('labels', []) as $label) { - $searchValues[] = 'label:' . $label; - } - - $search = implode(' ', \array_filter($searchValues)); - - return $search; - }, - function (mixed $value) { - return $value; - } -); - -Database::addFilter( - 'subQueryTargets', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - return Authorization::skip(fn () => $database - ->find('targets', [ - Query::equal('userInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBQUERY) - ])); - } -); - -Database::addFilter( - 'subQueryTopicTargets', - function (mixed $value) { - return; - }, - function (mixed $value, Document $document, Database $database) { - $targetIds = Authorization::skip(fn () => \array_map( - fn ($document) => $document->getAttribute('targetInternalId'), - $database->find('subscribers', [ - Query::equal('topicInternalId', [$document->getInternalId()]), - Query::limit(APP_LIMIT_SUBSCRIBERS_SUBQUERY) - ]) - )); - if (\count($targetIds) > 0) { - return $database->skipValidation(fn () => $database->find('targets', [ - Query::equal('$internalId', $targetIds) - ])); - } - return []; - } -); - -Database::addFilter( - 'providerSearch', - function (mixed $value, Document $provider) { - $searchValues = [ - $provider->getId(), - $provider->getAttribute('name', ''), - $provider->getAttribute('provider', ''), - $provider->getAttribute('type', '') - ]; - - $search = \implode(' ', \array_filter($searchValues)); - - return $search; - }, - function (mixed $value) { - return $value; - } -); - -Database::addFilter( - 'topicSearch', - function (mixed $value, Document $topic) { - $searchValues = [ - $topic->getId(), - $topic->getAttribute('name', ''), - $topic->getAttribute('description', ''), - ]; - - $search = \implode(' ', \array_filter($searchValues)); - - return $search; - }, - function (mixed $value) { - return $value; - } -); - -Database::addFilter( - 'messageSearch', - function (mixed $value, Document $message) { - $searchValues = [ - $message->getId(), - $message->getAttribute('description', ''), - $message->getAttribute('status', ''), - ]; - - $data = \json_decode($message->getAttribute('data', []), true); - $providerType = $message->getAttribute('providerType', ''); - - if ($providerType === MESSAGE_TYPE_EMAIL) { - $searchValues = \array_merge($searchValues, [$data['subject'], MESSAGE_TYPE_EMAIL]); - } elseif ($providerType === MESSAGE_TYPE_SMS) { - $searchValues = \array_merge($searchValues, [$data['content'], MESSAGE_TYPE_SMS]); - } else { - $searchValues = \array_merge($searchValues, [$data['title'], MESSAGE_TYPE_PUSH]); - } - - $search = \implode(' ', \array_filter($searchValues)); - - return $search; - }, - function (mixed $value) { - return $value; - } -); - -/** - * DB Formats - */ -Structure::addFormat(APP_DATABASE_ATTRIBUTE_EMAIL, function () { - return new Email(); -}, Database::VAR_STRING); - -Structure::addFormat(APP_DATABASE_ATTRIBUTE_DATETIME, function () { - return new DatetimeValidator(); -}, Database::VAR_DATETIME); - -Structure::addFormat(APP_DATABASE_ATTRIBUTE_ENUM, function ($attribute) { - $elements = $attribute['formatOptions']['elements']; - return new WhiteList($elements, true); -}, Database::VAR_STRING); - -Structure::addFormat(APP_DATABASE_ATTRIBUTE_IP, function () { - return new IP(); -}, Database::VAR_STRING); - -Structure::addFormat(APP_DATABASE_ATTRIBUTE_URL, function () { - return new URL(); -}, Database::VAR_STRING); - -Structure::addFormat(APP_DATABASE_ATTRIBUTE_INT_RANGE, function ($attribute) { - $min = $attribute['formatOptions']['min'] ?? -INF; - $max = $attribute['formatOptions']['max'] ?? INF; - return new Range($min, $max, Range::TYPE_INTEGER); -}, Database::VAR_INTEGER); - -Structure::addFormat(APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, function ($attribute) { - $min = $attribute['formatOptions']['min'] ?? -INF; - $max = $attribute['formatOptions']['max'] ?? INF; - return new Range($min, $max, Range::TYPE_FLOAT); -}, Database::VAR_FLOAT); - -/* - * Registry - */ -$register->set('logger', function () { - // Register error logger - $providerName = System::getEnv('_APP_LOGGING_PROVIDER', ''); - $providerConfig = System::getEnv('_APP_LOGGING_CONFIG', ''); - - try { - $loggingProvider = new DSN($providerConfig ?? ''); - - $providerName = $loggingProvider->getScheme(); - $providerConfig = match ($providerName) { - 'sentry' => ['key' => $loggingProvider->getPassword(), 'projectId' => $loggingProvider->getUser() ?? '', 'host' => 'https://' . $loggingProvider->getHost()], - 'logowl' => ['ticket' => $loggingProvider->getUser() ?? '', 'host' => $loggingProvider->getHost()], - default => ['key' => $loggingProvider->getHost()], - }; - } catch (Throwable $th) { - // Fallback for older Appwrite versions up to 1.5.x that use _APP_LOGGING_PROVIDER and _APP_LOGGING_CONFIG environment variables - Console::warning('Using deprecated logging configuration. Please update your configuration to use DSN format.' . $th->getMessage()); - $configChunks = \explode(";", $providerConfig); - - $providerConfig = match ($providerName) { - 'sentry' => [ 'key' => $configChunks[0], 'projectId' => $configChunks[1] ?? '', 'host' => '',], - 'logowl' => ['ticket' => $configChunks[0] ?? '', 'host' => ''], - default => ['key' => $providerConfig], - }; - } - - if (empty($providerName) || empty($providerConfig)) { - return; - } - - if (!Logger::hasProvider($providerName)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled"); - } - - try { - $adapter = match ($providerName) { - 'sentry' => new Sentry($providerConfig['projectId'], $providerConfig['key'], $providerConfig['host']), - 'logowl' => new LogOwl($providerConfig['ticket'], $providerConfig['host']), - 'raygun' => new Raygun($providerConfig['key']), - 'appsignal' => new AppSignal($providerConfig['key']), - default => null - }; - } catch (Throwable $th) { - $adapter = null; - } - - if ($adapter === null) { - Console::error("Logging provider not supported. Logging is disabled"); - return; - } - - return new Logger($adapter); -}); - -$register->set('pools', function () { - $group = new Group(); - - $fallbackForDB = 'db_main=' . AppwriteURL::unparse([ - 'scheme' => 'mariadb', - 'host' => System::getEnv('_APP_DB_HOST', 'mariadb'), - 'port' => System::getEnv('_APP_DB_PORT', '3306'), - 'user' => System::getEnv('_APP_DB_USER', ''), - 'pass' => System::getEnv('_APP_DB_PASS', ''), - 'path' => System::getEnv('_APP_DB_SCHEMA', ''), - ]); - $fallbackForRedis = 'redis_main=' . AppwriteURL::unparse([ - 'scheme' => 'redis', - 'host' => System::getEnv('_APP_REDIS_HOST', 'redis'), - 'port' => System::getEnv('_APP_REDIS_PORT', '6379'), - 'user' => System::getEnv('_APP_REDIS_USER', ''), - 'pass' => System::getEnv('_APP_REDIS_PASS', ''), - ]); - - $connections = [ - 'console' => [ - 'type' => 'database', - 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_CONSOLE', $fallbackForDB), - 'multiple' => false, - 'schemes' => ['mariadb', 'mysql'], - ], - 'database' => [ - 'type' => 'database', - 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_PROJECT', $fallbackForDB), - 'multiple' => true, - 'schemes' => ['mariadb', 'mysql'], - ], - 'queue' => [ - 'type' => 'queue', - 'dsns' => System::getEnv('_APP_CONNECTIONS_QUEUE', $fallbackForRedis), - 'multiple' => false, - 'schemes' => ['redis'], - ], - 'pubsub' => [ - 'type' => 'pubsub', - 'dsns' => System::getEnv('_APP_CONNECTIONS_PUBSUB', $fallbackForRedis), - 'multiple' => false, - 'schemes' => ['redis'], - ], - 'cache' => [ - 'type' => 'cache', - 'dsns' => System::getEnv('_APP_CONNECTIONS_CACHE', $fallbackForRedis), - 'multiple' => true, - 'schemes' => ['redis'], - ], - ]; - - $maxConnections = System::getEnv('_APP_CONNECTIONS_MAX', 151); - $instanceConnections = $maxConnections / System::getEnv('_APP_POOL_CLIENTS', 14); - - $multiprocessing = System::getEnv('_APP_SERVER_MULTIPROCESS', 'disabled') === 'enabled'; - - if ($multiprocessing) { - $workerCount = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); - } else { - $workerCount = 1; - } - - if ($workerCount > $instanceConnections) { - throw new \Exception('Pool size is too small. Increase the number of allowed database connections or decrease the number of workers.', 500); - } - - $poolSize = (int)($instanceConnections / $workerCount); - - foreach ($connections as $key => $connection) { - $type = $connection['type'] ?? ''; - $multiple = $connection['multiple'] ?? false; - $schemes = $connection['schemes'] ?? []; - $config = []; - $dsns = explode(',', $connection['dsns'] ?? ''); - foreach ($dsns as &$dsn) { - $dsn = explode('=', $dsn); - $name = ($multiple) ? $key . '_' . $dsn[0] : $key; - $dsn = $dsn[1] ?? ''; - $config[] = $name; - if (empty($dsn)) { - //throw new Exception(Exception::GENERAL_SERVER_ERROR, "Missing value for DSN connection in {$key}"); - continue; - } - - $dsn = new DSN($dsn); - $dsnHost = $dsn->getHost(); - $dsnPort = $dsn->getPort(); - $dsnUser = $dsn->getUser(); - $dsnPass = $dsn->getPassword(); - $dsnScheme = $dsn->getScheme(); - $dsnDatabase = $dsn->getPath(); - - if (!in_array($dsnScheme, $schemes)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid console database scheme"); - } - - /** - * Get Resource - * - * Creation could be reused across connection types like database, cache, queue, etc. - * - * Resource assignment to an adapter will happen below. - */ - $resource = match ($dsnScheme) { - '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( - PDO::ATTR_TIMEOUT => 3, // Seconds - PDO::ATTR_PERSISTENT => true, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - PDO::ATTR_EMULATE_PREPARES => true, - PDO::ATTR_STRINGIFY_FETCHES => true - )); - }); - }, - 'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) { - $redis = new Redis(); - @$redis->pconnect($dsnHost, (int)$dsnPort); - if ($dsnPass) { - $redis->auth($dsnPass); - } - $redis->setOption(Redis::OPT_READ_TIMEOUT, -1); - - return $redis; - }, - default => throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid scheme'), - }; - - $pool = new Pool($name, $poolSize, function () use ($type, $resource, $dsn) { - // Get Adapter - switch ($type) { - case 'database': - $adapter = match ($dsn->getScheme()) { - 'mariadb' => new MariaDB($resource()), - 'mysql' => new MySQL($resource()), - default => null - }; - - $adapter->setDatabase($dsn->getPath()); - break; - case 'pubsub': - $adapter = match ($dsn->getScheme()) { - 'redis' => new PubSub($resource()), - default => null - }; - break; - case 'queue': - $adapter = match ($dsn->getScheme()) { - 'redis' => new Queue\Connection\Redis($dsn->getHost(), $dsn->getPort()), - default => null - }; - break; - case 'cache': - $adapter = match ($dsn->getScheme()) { - 'redis' => new RedisCache($resource()), - default => null - }; - break; - - default: - throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation."); - } - - return $adapter; - }); - - $group->add($pool); - } - - Config::setParam('pools-' . $key, $config); - } - - return $group; -}); - -$register->set('db', function () { - // This is usually for our workers or CLI commands scope - $dbHost = System::getEnv('_APP_DB_HOST', ''); - $dbPort = System::getEnv('_APP_DB_PORT', ''); - $dbUser = System::getEnv('_APP_DB_USER', ''); - $dbPass = System::getEnv('_APP_DB_PASS', ''); - $dbScheme = System::getEnv('_APP_DB_SCHEMA', ''); - - return new PDO( - "mysql:host={$dbHost};port={$dbPort};dbname={$dbScheme};charset=utf8mb4", - $dbUser, - $dbPass, - SQL::getPDOAttributes() - ); -}); - -$register->set('smtp', function () { - $mail = new PHPMailer(true); - - $mail->isSMTP(); - - $username = System::getEnv('_APP_SMTP_USERNAME'); - $password = System::getEnv('_APP_SMTP_PASSWORD'); - - $mail->XMailer = 'Appwrite Mailer'; - $mail->Host = System::getEnv('_APP_SMTP_HOST', 'smtp'); - $mail->Port = System::getEnv('_APP_SMTP_PORT', 25); - $mail->SMTPAuth = !empty($username) && !empty($password); - $mail->Username = $username; - $mail->Password = $password; - $mail->SMTPSecure = System::getEnv('_APP_SMTP_SECURE', ''); - $mail->SMTPAutoTLS = false; - $mail->CharSet = 'UTF-8'; - - $from = \urldecode(System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); - $email = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); - - $mail->setFrom($email, $from); - $mail->addReplyTo($email, $from); - - $mail->isHTML(true); - - return $mail; -}); -$register->set('geodb', function () { - return new Reader(__DIR__ . '/assets/dbip/dbip-country-lite-2024-09.mmdb'); -}); -$register->set('passwordsDictionary', function () { - $content = \file_get_contents(__DIR__ . '/assets/security/10k-common-passwords'); - $content = explode("\n", $content); - $content = array_flip($content); - return $content; -}); -$register->set('promiseAdapter', function () { - return new Swoole(); -}); -$register->set('hooks', function () { - return new Hooks(); -}); -/* - * Localization - */ -Locale::$exceptions = false; - -$locales = Config::getParam('locale-codes', []); - -foreach ($locales as $locale) { - $code = $locale['code']; - - $path = __DIR__ . '/config/locale/translations/' . $code . '.json'; - - if (!\file_exists($path)) { - $path = __DIR__ . '/config/locale/translations/' . \substr($code, 0, 2) . '.json'; // if `ar-ae` doesn't exist, look for `ar` - if (!\file_exists($path)) { - $path = __DIR__ . '/config/locale/translations/en.json'; // if none translation exists, use default from `en.json` - } - } - - Locale::setLanguageFromJSON($code, $path); -} +require_once __DIR__ . '/init/constants.php'; +require_once __DIR__ . '/init/configs.php'; +require_once __DIR__ . '/init/database/filters.php'; +require_once __DIR__ . '/init/database/formats.php'; +require_once __DIR__ . '/init/locales.php'; +require_once __DIR__ . '/init/registers.php'; +require_once __DIR__ . '/init/resources.php'; \stream_context_set_default([ // Set global user agent and http settings 'http' => [ @@ -1100,734 +39,3 @@ foreach ($locales as $locale) { 'timeout' => 2, ], ]); - -// Runtime Execution -App::setResource('log', fn () => new Log()); -App::setResource('logger', function ($register) { - return $register->get('logger'); -}, ['register']); - -App::setResource('hooks', function ($register) { - return $register->get('hooks'); -}, ['register']); - -App::setResource('register', fn () => $register); -App::setResource('locale', fn () => new Locale(System::getEnv('_APP_LOCALE', 'en'))); - -App::setResource('localeCodes', function () { - return array_map(fn ($locale) => $locale['code'], Config::getParam('locale-codes', [])); -}); - -// Queues -App::setResource('queue', function (Group $pools) { - return $pools->get('queue')->pop()->getResource(); -}, ['pools']); -App::setResource('queueForMessaging', function (Connection $queue) { - return new Messaging($queue); -}, ['queue']); -App::setResource('queueForMails', function (Connection $queue) { - return new Mail($queue); -}, ['queue']); -App::setResource('queueForBuilds', function (Connection $queue) { - return new Build($queue); -}, ['queue']); -App::setResource('queueForDatabase', function (Connection $queue) { - return new EventDatabase($queue); -}, ['queue']); -App::setResource('queueForDeletes', function (Connection $queue) { - return new Delete($queue); -}, ['queue']); -App::setResource('queueForEvents', function (Connection $queue) { - return new Event($queue); -}, ['queue']); -App::setResource('queueForWebhooks', function (Connection $queue) { - return new Webhook($queue); -}, ['queue']); -App::setResource('queueForRealtime', function () { - return new Realtime(); -}, []); -App::setResource('queueForAudits', function (Connection $queue) { - return new Audit($queue); -}, ['queue']); -App::setResource('queueForFunctions', function (Connection $queue) { - return new Func($queue); -}, ['queue']); -App::setResource('queueForUsage', function (Connection $queue) { - return new Usage($queue); -}, ['queue']); -App::setResource('queueForCertificates', function (Connection $queue) { - return new Certificate($queue); -}, ['queue']); -App::setResource('queueForMigrations', function (Connection $queue) { - return new Migration($queue); -}, ['queue']); -App::setResource('clients', function ($request, $console, $project) { - $console->setAttribute('platforms', [ // Always allow current host - '$collection' => ID::custom('platforms'), - 'name' => 'Current Host', - 'type' => Origin::CLIENT_TYPE_WEB, - 'hostname' => $request->getHostname(), - ], Document::SET_TYPE_APPEND); - - $hostnames = explode(',', System::getEnv('_APP_CONSOLE_HOSTNAMES', '')); - $validator = new Hostname(); - foreach ($hostnames as $hostname) { - $hostname = trim($hostname); - if (!$validator->isValid($hostname)) { - continue; - } - $console->setAttribute('platforms', [ - '$collection' => ID::custom('platforms'), - 'type' => Origin::CLIENT_TYPE_WEB, - 'name' => $hostname, - 'hostname' => $hostname, - ], Document::SET_TYPE_APPEND); - } - - /** - * Get All verified client URLs for both console and current projects - * + Filter for duplicated entries - */ - $clientsConsole = \array_map( - fn ($node) => $node['hostname'], - \array_filter( - $console->getAttribute('platforms', []), - fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && !empty($node['hostname'])) - ) - ); - - $clients = $clientsConsole; - $platforms = $project->getAttribute('platforms', []); - - foreach ($platforms as $node) { - if ( - isset($node['type']) && - ($node['type'] === Origin::CLIENT_TYPE_WEB || - $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && - !empty($node['hostname']) - ) { - $clients[] = $node['hostname']; - } - } - - return \array_unique($clients); -}, ['request', 'console', 'project']); - -App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForConsole) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Document $project */ - /** @var Utopia\Database\Database $dbForProject */ - /** @var Utopia\Database\Database $dbForConsole */ - /** @var string $mode */ - - Authorization::setDefaultStatus(true); - - Auth::setCookieName('a_session_' . $project->getId()); - - if (APP_MODE_ADMIN === $mode) { - Auth::setCookieName('a_session_' . $console->getId()); - } - - $session = Auth::decodeSession( - $request->getCookie( - Auth::$cookieName, // Get sessions - $request->getCookie(Auth::$cookieName . '_legacy', '') - ) - ); - - // Get session from header for SSR clients - if (empty($session['id']) && empty($session['secret'])) { - $sessionHeader = $request->getHeader('x-appwrite-session', ''); - - if (!empty($sessionHeader)) { - $session = Auth::decodeSession($sessionHeader); - } - } - - // Get fallback session from old clients (no SameSite support) or clients who block 3rd-party cookies - if ($response) { - $response->addHeader('X-Debug-Fallback', 'false'); - } - - if (empty($session['id']) && empty($session['secret'])) { - if ($response) { - $response->addHeader('X-Debug-Fallback', 'true'); - } - $fallback = $request->getHeader('x-fallback-cookies', ''); - $fallback = \json_decode($fallback, true); - $session = Auth::decodeSession(((isset($fallback[Auth::$cookieName])) ? $fallback[Auth::$cookieName] : '')); - } - - Auth::$unique = $session['id'] ?? ''; - Auth::$secret = $session['secret'] ?? ''; - - if (APP_MODE_ADMIN !== $mode) { - if ($project->isEmpty()) { - $user = new Document([]); - } else { - if ($project->getId() === 'console') { - $user = $dbForConsole->getDocument('users', Auth::$unique); - } else { - $user = $dbForProject->getDocument('users', Auth::$unique); - } - } - } else { - $user = $dbForConsole->getDocument('users', Auth::$unique); - } - - if ( - $user->isEmpty() // Check a document has been found in the DB - || !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret) - ) { // Validate user has valid login token - $user = new Document([]); - } - - // if (APP_MODE_ADMIN === $mode) { - // if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) { - // Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. - // } else { - // $user = new Document([]); - // } - // } - - $authJWT = $request->getHeader('x-appwrite-jwt', ''); - - if (!empty($authJWT) && !$project->isEmpty()) { // JWT authentication - $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); - - try { - $payload = $jwt->decode($authJWT); - } catch (JWTException $error) { - throw new Exception(Exception::USER_JWT_INVALID, 'Failed to verify JWT. ' . $error->getMessage()); - } - - $jwtUserId = $payload['userId'] ?? ''; - if (!empty($jwtUserId)) { - $user = $dbForProject->getDocument('users', $jwtUserId); - } - - $jwtSessionId = $payload['sessionId'] ?? ''; - if (!empty($jwtSessionId)) { - if (empty($user->find('$id', $jwtSessionId, 'sessions'))) { // Match JWT to active token - $user = new Document([]); - } - } - } - - $dbForProject->setMetadata('user', $user->getId()); - $dbForConsole->setMetadata('user', $user->getId()); - - return $user; -}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForConsole']); - -App::setResource('project', function ($dbForConsole, $request, $console) { - /** @var Appwrite\Utopia\Request $request */ - /** @var Utopia\Database\Database $dbForConsole */ - /** @var Utopia\Database\Document $console */ - - $projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', '')); - - if (empty($projectId) || $projectId === 'console') { - return $console; - } - - $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); - - return $project; -}, ['dbForConsole', 'request', 'console']); - -App::setResource('session', function (Document $user) { - if ($user->isEmpty()) { - return; - } - - $sessions = $user->getAttribute('sessions', []); - $sessionId = Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret); - - if (!$sessionId) { - return; - } - - foreach ($sessions as $session) {/** @var Document $session */ - if ($sessionId === $session->getId()) { - return $session; - } - } - - return; -}, ['user']); - -App::setResource('console', function () { - return new Document([ - '$id' => ID::custom('console'), - '$internalId' => ID::custom('console'), - 'name' => 'Appwrite', - '$collection' => ID::custom('projects'), - 'description' => 'Appwrite core engine', - 'logo' => '', - 'teamId' => null, - 'webhooks' => [], - 'keys' => [], - 'platforms' => [ - [ - '$collection' => ID::custom('platforms'), - 'name' => 'Localhost', - 'type' => Origin::CLIENT_TYPE_WEB, - 'hostname' => 'localhost', - ], // Current host is added on app init - ], - 'legalName' => '', - 'legalCountry' => '', - 'legalState' => '', - 'legalCity' => '', - 'legalAddress' => '', - 'legalTaxId' => '', - 'auths' => [ - 'mockNumbers' => [], - 'invites' => System::getEnv('_APP_CONSOLE_INVITES', 'enabled') === 'enabled', - 'limit' => (System::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled') === 'enabled') ? 1 : 0, // limit signup to 1 user - 'duration' => Auth::TOKEN_EXPIRATION_LOGIN_LONG, // 1 Year in seconds - 'sessionAlerts' => System::getEnv('_APP_CONSOLE_SESSION_ALERTS', 'disabled') === 'enabled' - ], - 'authWhitelistEmails' => (!empty(System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [], - 'authWhitelistIPs' => (!empty(System::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', System::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [], - 'oAuthProviders' => [ - 'githubEnabled' => true, - 'githubSecret' => System::getEnv('_APP_CONSOLE_GITHUB_SECRET', ''), - 'githubAppid' => System::getEnv('_APP_CONSOLE_GITHUB_APP_ID', '') - ], - ]); -}, []); - -App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, Cache $cache, Document $project) { - if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; - } - - 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')); - } - - $dbAdapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); - - $database - ->setMetadata('host', \gethostname()) - ->setMetadata('project', $project->getId()) - ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS) - ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); - - 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')); - } - - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { - $database - ->setSharedTables(true) - ->setTenant($project->getInternalId()) - ->setNamespace($dsn->getParam('namespace')); - } else { - $database - ->setSharedTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } - - return $database; -}, ['pools', 'dbForConsole', 'cache', 'project']); - -App::setResource('dbForConsole', function (Group $pools, Cache $cache) { - $dbAdapter = $pools - ->get('console') - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); - - $database - ->setNamespace('_console') - ->setMetadata('host', \gethostname()) - ->setMetadata('project', 'console') - ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS) - ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); - - return $database; -}, ['pools', 'cache']); - -App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) { - $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - - return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases) { - if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; - } - - 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')); - } - - $configure = (function (Database $database) use ($project, $dsn) { - $database - ->setMetadata('host', \gethostname()) - ->setMetadata('project', $project->getId()) - ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS) - ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); - - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { - $database - ->setSharedTables(true) - ->setTenant($project->getInternalId()) - ->setNamespace($dsn->getParam('namespace')); - } else { - $database - ->setSharedTables(false) - ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); - } - }); - - if (isset($databases[$dsn->getHost()])) { - $database = $databases[$dsn->getHost()]; - $configure($database); - return $database; - } - - $dbAdapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); - $databases[$dsn->getHost()] = $database; - $configure($database); - - return $database; - }; -}, ['pools', 'dbForConsole', 'cache']); - -App::setResource('cache', function (Group $pools) { - $list = Config::getParam('pools-cache', []); - $adapters = []; - - foreach ($list as $value) { - $adapters[] = $pools - ->get($value) - ->pop() - ->getResource() - ; - } - - return new Cache(new Sharding($adapters)); -}, ['pools']); - -App::setResource('deviceForLocal', function () { - return new Local(); -}); - -App::setResource('deviceForFiles', function ($project) { - return getDevice(APP_STORAGE_UPLOADS . '/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']); - -function getDevice(string $root, string $connection = ''): Device -{ - $connection = !empty($connection) ? $connection : System::getEnv('_APP_CONNECTIONS_STORAGE', ''); - - if (!empty($connection)) { - $acl = 'private'; - $device = Storage::DEVICE_LOCAL; - $accessKey = ''; - $accessSecret = ''; - $bucket = ''; - $region = ''; - - try { - $dsn = new DSN($connection); - $device = $dsn->getScheme(); - $accessKey = $dsn->getUser() ?? ''; - $accessSecret = $dsn->getPassword() ?? ''; - $bucket = $dsn->getPath() ?? ''; - $region = $dsn->getParam('region'); - } catch (\Throwable $e) { - Console::warning($e->getMessage() . 'Invalid DSN. Defaulting to Local device.'); - } - - switch ($device) { - case Storage::DEVICE_S3: - return new S3($root, $accessKey, $accessSecret, $bucket, $region, $acl); - case STORAGE::DEVICE_DO_SPACES: - $device = new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl); - $device->setHttpVersion(S3::HTTP_VERSION_1_1); - return $device; - case Storage::DEVICE_BACKBLAZE: - return new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl); - case Storage::DEVICE_LINODE: - return new Linode($root, $accessKey, $accessSecret, $bucket, $region, $acl); - case Storage::DEVICE_WASABI: - return new Wasabi($root, $accessKey, $accessSecret, $bucket, $region, $acl); - case Storage::DEVICE_LOCAL: - default: - return new Local($root); - } - } else { - switch (strtolower(System::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) ?? '')) { - case Storage::DEVICE_LOCAL: - default: - return new Local($root); - case Storage::DEVICE_S3: - $s3AccessKey = System::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''); - $s3SecretKey = System::getEnv('_APP_STORAGE_S3_SECRET', ''); - $s3Region = System::getEnv('_APP_STORAGE_S3_REGION', ''); - $s3Bucket = System::getEnv('_APP_STORAGE_S3_BUCKET', ''); - $s3Acl = 'private'; - return new S3($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl); - case Storage::DEVICE_DO_SPACES: - $doSpacesAccessKey = System::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', ''); - $doSpacesSecretKey = System::getEnv('_APP_STORAGE_DO_SPACES_SECRET', ''); - $doSpacesRegion = System::getEnv('_APP_STORAGE_DO_SPACES_REGION', ''); - $doSpacesBucket = System::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''); - $doSpacesAcl = 'private'; - $device = new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl); - $device->setHttpVersion(S3::HTTP_VERSION_1_1); - return $device; - case Storage::DEVICE_BACKBLAZE: - $backblazeAccessKey = System::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', ''); - $backblazeSecretKey = System::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', ''); - $backblazeRegion = System::getEnv('_APP_STORAGE_BACKBLAZE_REGION', ''); - $backblazeBucket = System::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', ''); - $backblazeAcl = 'private'; - return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl); - case Storage::DEVICE_LINODE: - $linodeAccessKey = System::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', ''); - $linodeSecretKey = System::getEnv('_APP_STORAGE_LINODE_SECRET', ''); - $linodeRegion = System::getEnv('_APP_STORAGE_LINODE_REGION', ''); - $linodeBucket = System::getEnv('_APP_STORAGE_LINODE_BUCKET', ''); - $linodeAcl = 'private'; - return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl); - case Storage::DEVICE_WASABI: - $wasabiAccessKey = System::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', ''); - $wasabiSecretKey = System::getEnv('_APP_STORAGE_WASABI_SECRET', ''); - $wasabiRegion = System::getEnv('_APP_STORAGE_WASABI_REGION', ''); - $wasabiBucket = System::getEnv('_APP_STORAGE_WASABI_BUCKET', ''); - $wasabiAcl = 'private'; - return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl); - } - } -} - -App::setResource('mode', function ($request) { - /** @var Appwrite\Utopia\Request $request */ - - /** - * Defines the mode for the request: - * - 'default' => Requests for Client and Server Side - * - 'admin' => Request from the Console on non-console projects - */ - return $request->getParam('mode', $request->getHeader('x-appwrite-mode', APP_MODE_DEFAULT)); -}, ['request']); - -App::setResource('geodb', function ($register) { - /** @var Utopia\Registry\Registry $register */ - return $register->get('geodb'); -}, ['register']); - -App::setResource('passwordsDictionary', function ($register) { - /** @var Utopia\Registry\Registry $register */ - return $register->get('passwordsDictionary'); -}, ['register']); - - -App::setResource('servers', function () { - $platforms = Config::getParam('platforms'); - $server = $platforms[APP_PLATFORM_SERVER]; - - $languages = array_map(function ($language) { - return strtolower($language['name']); - }, $server['sdks']); - - return $languages; -}); - -App::setResource('promiseAdapter', function ($register) { - return $register->get('promiseAdapter'); -}, ['register']); - -App::setResource('schema', function ($utopia, $dbForProject) { - - $complexity = function (int $complexity, array $args) { - $queries = Query::parseQueries($args['queries'] ?? []); - $query = Query::getByType($queries, [Query::TYPE_LIMIT])[0] ?? null; - $limit = $query ? $query->getValue() : APP_LIMIT_LIST_DEFAULT; - - return $complexity * $limit; - }; - - $attributes = function (int $limit, int $offset) use ($dbForProject) { - $attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [ - Query::limit($limit), - Query::offset($offset), - ])); - - return \array_map(function ($attr) { - return $attr->getArrayCopy(); - }, $attrs); - }; - - $urls = [ - 'list' => function (string $databaseId, string $collectionId, array $args) { - return "/v1/databases/$databaseId/collections/$collectionId/documents"; - }, - 'create' => function (string $databaseId, string $collectionId, array $args) { - return "/v1/databases/$databaseId/collections/$collectionId/documents"; - }, - 'read' => function (string $databaseId, string $collectionId, array $args) { - return "/v1/databases/$databaseId/collections/$collectionId/documents/{$args['documentId']}"; - }, - 'update' => function (string $databaseId, string $collectionId, array $args) { - return "/v1/databases/$databaseId/collections/$collectionId/documents/{$args['documentId']}"; - }, - 'delete' => function (string $databaseId, string $collectionId, array $args) { - return "/v1/databases/$databaseId/collections/$collectionId/documents/{$args['documentId']}"; - }, - ]; - - $params = [ - 'list' => function (string $databaseId, string $collectionId, array $args) { - return [ 'queries' => $args['queries']]; - }, - 'create' => function (string $databaseId, string $collectionId, array $args) { - $id = $args['id'] ?? 'unique()'; - $permissions = $args['permissions'] ?? null; - - unset($args['id']); - unset($args['permissions']); - - // Order must be the same as the route params - return [ - 'databaseId' => $databaseId, - 'documentId' => $id, - 'collectionId' => $collectionId, - 'data' => $args, - 'permissions' => $permissions, - ]; - }, - 'update' => function (string $databaseId, string $collectionId, array $args) { - $documentId = $args['id']; - $permissions = $args['permissions'] ?? null; - - unset($args['id']); - unset($args['permissions']); - - // Order must be the same as the route params - return [ - 'databaseId' => $databaseId, - 'collectionId' => $collectionId, - 'documentId' => $documentId, - 'data' => $args, - 'permissions' => $permissions, - ]; - }, - ]; - - return Schema::build( - $utopia, - $complexity, - $attributes, - $urls, - $params, - ); -}, ['utopia', 'dbForProject']); - -App::setResource('contributors', function () { - $path = 'app/config/contributors.json'; - $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; - return $list; -}); - -App::setResource('employees', function () { - $path = 'app/config/employees.json'; - $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; - return $list; -}); - -App::setResource('heroes', function () { - $path = 'app/config/heroes.json'; - $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; - return $list; -}); - -App::setResource('gitHub', function (Cache $cache) { - return new VcsGitHub($cache); -}, ['cache']); - -App::setResource('requestTimestamp', function ($request) { - //TODO: Move this to the Request class itself - $timestampHeader = $request->getHeader('x-appwrite-timestamp'); - $requestTimestamp = null; - if (!empty($timestampHeader)) { - try { - $requestTimestamp = new \DateTime($timestampHeader); - } catch (\Throwable $e) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid X-Appwrite-Timestamp header value'); - } - } - return $requestTimestamp; -}, ['request']); - -App::setResource('plan', function (array $plan = []) { - return []; -}); - -App::setResource('team', function (Document $project, Database $dbForConsole, App $utopia, Request $request) { - $teamInternalId = ''; - if ($project->getId() !== 'console') { - $teamInternalId = $project->getAttribute('teamInternalId', ''); - } else { - $route = $utopia->match($request); - $path = $route->getPath(); - if (str_starts_with($path, '/v1/projects/:projectId')) { - $uri = $request->getURI(); - $pid = explode('/', $uri)[3]; - $p = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $pid)); - $teamInternalId = $p->getAttribute('teamInternalId', ''); - } elseif ($path === '/v1/projects') { - $teamId = $request->getParam('teamId', ''); - $team = Authorization::skip(fn () => $dbForConsole->getDocument('teams', $teamId)); - return $team; - } - } - - $team = Authorization::skip(function () use ($dbForConsole, $teamInternalId) { - return $dbForConsole->findOne('teams', [ - Query::equal('$internalId', [$teamInternalId]), - ]); - }); - - return $team; -}, ['project', 'dbForConsole', 'utopia', 'request']); - -App::setResource( - 'isResourceBlocked', - fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false -); diff --git a/app/init/configs.php b/app/init/configs.php new file mode 100644 index 0000000000..6cd57faa93 --- /dev/null +++ b/app/init/configs.php @@ -0,0 +1,40 @@ +<?php + +use Utopia\Config\Config; + +Config::load('template-runtimes', __DIR__ . '/../config/template-runtimes.php'); +Config::load('events', __DIR__ . '/../config/events.php'); +Config::load('auth', __DIR__ . '/../config/auth.php'); +Config::load('apis', __DIR__ . '/../config/apis.php'); // List of APIs +Config::load('errors', __DIR__ . '/../config/errors.php'); +Config::load('oAuthProviders', __DIR__ . '/../config/oAuthProviders.php'); +Config::load('platforms', __DIR__ . '/../config/platforms.php'); +Config::load('console', __DIR__ . '/../config/console.php'); +Config::load('collections', __DIR__ . '/../config/collections.php'); +Config::load('frameworks', __DIR__ . '/../config/frameworks.php'); +Config::load('runtimes', __DIR__ . '/../config/runtimes.php'); +Config::load('runtimes-v2', __DIR__ . '/../config/runtimes-v2.php'); +Config::load('usage', __DIR__ . '/../config/usage.php'); +Config::load('roles', __DIR__ . '/../config/roles.php'); // User roles and scopes +Config::load('scopes', __DIR__ . '/../config/scopes.php'); // User roles and scopes +Config::load('services', __DIR__ . '/../config/services.php'); // List of services +Config::load('variables', __DIR__ . '/../config/variables.php'); // List of env variables +Config::load('regions', __DIR__ . '/../config/regions.php'); // List of available regions +Config::load('avatar-browsers', __DIR__ . '/../config/avatars/browsers.php'); +Config::load('avatar-credit-cards', __DIR__ . '/../config/avatars/credit-cards.php'); +Config::load('avatar-flags', __DIR__ . '/../config/avatars/flags.php'); +Config::load('locale-codes', __DIR__ . '/../config/locale/codes.php'); +Config::load('locale-currencies', __DIR__ . '/../config/locale/currencies.php'); +Config::load('locale-eu', __DIR__ . '/../config/locale/eu.php'); +Config::load('locale-languages', __DIR__ . '/../config/locale/languages.php'); +Config::load('locale-phones', __DIR__ . '/../config/locale/phones.php'); +Config::load('locale-countries', __DIR__ . '/../config/locale/countries.php'); +Config::load('locale-continents', __DIR__ . '/../config/locale/continents.php'); +Config::load('locale-templates', __DIR__ . '/../config/locale/templates.php'); +Config::load('storage-logos', __DIR__ . '/../config/storage/logos.php'); +Config::load('storage-mimes', __DIR__ . '/../config/storage/mimes.php'); +Config::load('storage-inputs', __DIR__ . '/../config/storage/inputs.php'); +Config::load('storage-outputs', __DIR__ . '/../config/storage/outputs.php'); +Config::load('specifications', __DIR__ . '/../config/specifications.php'); +Config::load('templates-function', __DIR__ . '/../config/templates/function.php'); +Config::load('templates-site', __DIR__ . '/../config/templates/site.php'); diff --git a/app/init/constants.php b/app/init/constants.php new file mode 100644 index 0000000000..2b15f9fa0b --- /dev/null +++ b/app/init/constants.php @@ -0,0 +1,259 @@ +<?php + +use Appwrite\Platform\Modules\Compute\Specification; + +const APP_NAME = 'Appwrite'; +const APP_DOMAIN = 'appwrite.io'; +const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address +const APP_EMAIL_SECURITY = ''; // Default security email address +const APP_USERAGENT = APP_NAME . '-Server v%s. Please report abuse at %s'; +const APP_MODE_DEFAULT = 'default'; +const APP_MODE_ADMIN = 'admin'; +const APP_PAGING_LIMIT = 12; +const APP_LIMIT_COUNT = 5000; +const APP_LIMIT_USERS = 10_000; +const APP_LIMIT_USER_PASSWORD_HISTORY = 20; +const APP_LIMIT_USER_SESSIONS_MAX = 100; +const APP_LIMIT_USER_SESSIONS_DEFAULT = 10; +const APP_LIMIT_ANTIVIRUS = 20_000_000; //20MB +const APP_LIMIT_ENCRYPTION = 20_000_000; //20MB +const APP_LIMIT_COMPRESSION = 20_000_000; //20MB +const APP_LIMIT_ARRAY_PARAMS_SIZE = 100; // Default maximum of how many elements can there be in API parameter that expects array value +const APP_LIMIT_ARRAY_LABELS_SIZE = 1000; // Default maximum of how many labels elements can there be in API parameter that expects array value +const APP_LIMIT_ARRAY_ELEMENT_SIZE = 4096; // Default maximum length of element in array parameter represented by maximum URL length. +const APP_LIMIT_SUBQUERY = 1000; +const APP_LIMIT_SUBSCRIBERS_SUBQUERY = 1_000_000; +const APP_LIMIT_WRITE_RATE_DEFAULT = 60; // Default maximum write rate per rate period +const APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT = 60; // Default maximum write rate period in seconds +const APP_LIMIT_LIST_DEFAULT = 25; // Default maximum number of items to return in list API calls +const APP_KEY_ACCESS = 24 * 60 * 60; // 24 hours +const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours +const APP_PROJECT_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 = 4318; +const APP_VERSION_STABLE = '1.7.0'; +const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; +const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; +const APP_DATABASE_ATTRIBUTE_IP = 'ip'; +const APP_DATABASE_ATTRIBUTE_DATETIME = 'datetime'; +const APP_DATABASE_ATTRIBUTE_URL = 'url'; +const APP_DATABASE_ATTRIBUTE_INT_RANGE = 'intRange'; +const APP_DATABASE_ATTRIBUTE_FLOAT_RANGE = 'floatRange'; +const APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH = 1_073_741_824; // 2^32 bits / 4 bits per char +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_STORAGE_UPLOADS = '/storage/uploads'; +const APP_STORAGE_SITES = '/storage/sites'; +const APP_STORAGE_FUNCTIONS = '/storage/functions'; +const APP_STORAGE_BUILDS = '/storage/builds'; +const APP_STORAGE_CACHE = '/storage/cache'; +const APP_STORAGE_IMPORTS = '/storage/imports'; // Temporary storage for csv imports +const APP_STORAGE_CERTIFICATES = '/storage/certificates'; +const APP_STORAGE_CONFIG = '/storage/config'; +const APP_STORAGE_READ_BUFFER = 20 * (1000 * 1000); //20MB other names `APP_STORAGE_MEMORY_LIMIT`, `APP_STORAGE_MEMORY_BUFFER`, `APP_STORAGE_READ_LIMIT`, `APP_STORAGE_BUFFER_LIMIT` +const APP_SOCIAL_TWITTER = 'https://twitter.com/appwrite'; +const APP_SOCIAL_TWITTER_HANDLE = 'appwrite'; +const APP_SOCIAL_FACEBOOK = 'https://www.facebook.com/appwrite.io'; +const APP_SOCIAL_LINKEDIN = 'https://www.linkedin.com/company/appwrite'; +const APP_SOCIAL_INSTAGRAM = 'https://www.instagram.com/appwrite.io'; +const APP_SOCIAL_GITHUB = 'https://github.com/appwrite'; +const APP_SOCIAL_DISCORD = 'https://appwrite.io/discord'; +const APP_SOCIAL_DISCORD_CHANNEL = '564160730845151244'; +const APP_SOCIAL_DEV = 'https://dev.to/appwrite'; +const APP_SOCIAL_STACKSHARE = 'https://stackshare.io/appwrite'; +const APP_SOCIAL_YOUTUBE = 'https://www.youtube.com/c/appwrite?sub_confirmation=1'; +const APP_HOSTNAME_INTERNAL = 'appwrite'; +const APP_COMPUTE_CPUS_DEFAULT = 0.5; +const APP_COMPUTE_MEMORY_DEFAULT = 512; +const APP_COMPUTE_SPECIFICATION_DEFAULT = Specification::S_1VCPU_512MB; +const APP_PLATFORM_SERVER = 'server'; +const APP_PLATFORM_CLIENT = 'client'; +const APP_PLATFORM_CONSOLE = 'console'; + +// Database Reconnect +const DATABASE_RECONNECT_SLEEP = 2; +const DATABASE_RECONNECT_MAX_ATTEMPTS = 10; + +// Database Worker Types +const DATABASE_TYPE_CREATE_ATTRIBUTE = 'createAttribute'; +const DATABASE_TYPE_CREATE_INDEX = 'createIndex'; +const DATABASE_TYPE_DELETE_ATTRIBUTE = 'deleteAttribute'; +const DATABASE_TYPE_DELETE_INDEX = 'deleteIndex'; +const DATABASE_TYPE_DELETE_COLLECTION = 'deleteCollection'; +const DATABASE_TYPE_DELETE_DATABASE = 'deleteDatabase'; + +// Build Worker Types +const BUILD_TYPE_DEPLOYMENT = 'deployment'; +const BUILD_TYPE_RETRY = 'retry'; + +// Deletion Types +const DELETE_TYPE_DATABASES = 'databases'; +const DELETE_TYPE_DOCUMENT = 'document'; +const DELETE_TYPE_COLLECTIONS = 'collections'; +const DELETE_TYPE_PROJECTS = 'projects'; +const DELETE_TYPE_SITES = 'sites'; +const DELETE_TYPE_FUNCTIONS = 'functions'; +const DELETE_TYPE_DEPLOYMENTS = 'deployments'; +const DELETE_TYPE_USERS = 'users'; +const DELETE_TYPE_TEAM_PROJECTS = 'teams_projects'; +const DELETE_TYPE_EXECUTIONS = 'executions'; +const DELETE_TYPE_AUDIT = 'audit'; +const DELETE_TYPE_ABUSE = 'abuse'; +const DELETE_TYPE_USAGE = 'usage'; +const DELETE_TYPE_REALTIME = 'realtime'; +const DELETE_TYPE_BUCKETS = 'buckets'; +const DELETE_TYPE_INSTALLATIONS = 'installations'; +const DELETE_TYPE_RULES = 'rules'; +const DELETE_TYPE_SESSIONS = 'sessions'; +const DELETE_TYPE_CACHE_BY_TIMESTAMP = 'cacheByTimeStamp'; +const DELETE_TYPE_CACHE_BY_RESOURCE = 'cacheByResource'; +const DELETE_TYPE_SCHEDULES = 'schedules'; +const DELETE_TYPE_TOPIC = 'topic'; +const DELETE_TYPE_TARGET = 'target'; +const DELETE_TYPE_EXPIRED_TARGETS = 'invalid_targets'; +const DELETE_TYPE_SESSION_TARGETS = 'session_targets'; +const DELETE_TYPE_MAINTENANCE = 'maintenance'; + +// Message types +const MESSAGE_SEND_TYPE_INTERNAL = 'internal'; +const MESSAGE_SEND_TYPE_EXTERNAL = 'external'; +// Mail Types +const MAIL_TYPE_VERIFICATION = 'verification'; +const MAIL_TYPE_MAGIC_SESSION = 'magicSession'; +const MAIL_TYPE_RECOVERY = 'recovery'; +const MAIL_TYPE_INVITATION = 'invitation'; +const MAIL_TYPE_CERTIFICATE = 'certificate'; +// Auth Types +const APP_AUTH_TYPE_SESSION = 'Session'; +const APP_AUTH_TYPE_JWT = 'JWT'; +const APP_AUTH_TYPE_KEY = 'Key'; +const APP_AUTH_TYPE_ADMIN = 'Admin'; +// Response related +const MAX_OUTPUT_CHUNK_SIZE = 10 * 1024 * 1024; // 10MB +// Function headers +const FUNCTION_ALLOWLIST_HEADERS_REQUEST = ['content-type', 'agent', 'content-length', 'host']; +const FUNCTION_ALLOWLIST_HEADERS_RESPONSE = ['content-type', 'content-length']; +// Message types +const MESSAGE_TYPE_EMAIL = 'email'; +const MESSAGE_TYPE_SMS = 'sms'; +const MESSAGE_TYPE_PUSH = 'push'; +// API key types +const API_KEY_STANDARD = 'standard'; +const API_KEY_DYNAMIC = 'dynamic'; +// Usage metrics +const METRIC_TEAMS = 'teams'; +const METRIC_USERS = 'users'; +const METRIC_WEBHOOKS_SENT = 'webhooks.events.sent'; +const METRIC_WEBHOOKS_FAILED = 'webhooks.events.failed'; +const METRIC_WEBHOOK_ID_SENT = '{webhookInternalId}.webhooks.events.sent'; +const METRIC_WEBHOOK_ID_FAILED = '{webhookInternalId}.webhooks.events.failed'; +const METRIC_AUTH_METHOD_PHONE = 'auth.method.phone'; +const METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE = METRIC_AUTH_METHOD_PHONE . '.{countryCode}'; +const METRIC_MESSAGES = 'messages'; +const METRIC_MESSAGES_SENT = METRIC_MESSAGES . '.sent'; +const METRIC_MESSAGES_FAILED = METRIC_MESSAGES . '.failed'; +const METRIC_MESSAGES_TYPE = METRIC_MESSAGES . '.{type}'; +const METRIC_MESSAGES_TYPE_SENT = METRIC_MESSAGES . '.{type}.sent'; +const METRIC_MESSAGES_TYPE_FAILED = METRIC_MESSAGES . '.{type}.failed'; +const METRIC_MESSAGES_TYPE_PROVIDER = METRIC_MESSAGES . '.{type}.{provider}'; +const METRIC_MESSAGES_TYPE_PROVIDER_SENT = METRIC_MESSAGES . '.{type}.{provider}.sent'; +const METRIC_MESSAGES_TYPE_PROVIDER_FAILED = METRIC_MESSAGES . '.{type}.{provider}.failed'; +const METRIC_SESSIONS = 'sessions'; +const METRIC_DATABASES = 'databases'; +const METRIC_COLLECTIONS = 'collections'; +const METRIC_DATABASES_STORAGE = 'databases.storage'; +const METRIC_DATABASE_ID_COLLECTIONS = '{databaseInternalId}.collections'; +const METRIC_DATABASE_ID_STORAGE = '{databaseInternalId}.databases.storage'; +const METRIC_DOCUMENTS = 'documents'; +const METRIC_DATABASE_ID_DOCUMENTS = '{databaseInternalId}.documents'; +const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collectionInternalId}.documents'; +const METRIC_DATABASE_ID_COLLECTION_ID_STORAGE = '{databaseInternalId}.{collectionInternalId}.databases.storage'; +const METRIC_DATABASES_OPERATIONS_READS = 'databases.operations.reads'; +const METRIC_DATABASE_ID_OPERATIONS_READS = '{databaseInternalId}.databases.operations.reads'; +const METRIC_DATABASES_OPERATIONS_WRITES = 'databases.operations.writes'; +const METRIC_DATABASE_ID_OPERATIONS_WRITES = '{databaseInternalId}.databases.operations.writes'; +const METRIC_BUCKETS = 'buckets'; +const METRIC_FILES = 'files'; +const METRIC_FILES_STORAGE = 'files.storage'; +const METRIC_FILES_TRANSFORMATIONS = 'files.transformations'; +const METRIC_BUCKET_ID_FILES_TRANSFORMATIONS = '{bucketInternalId}.files.transformations'; +const METRIC_FILES_IMAGES_TRANSFORMED = 'files.imagesTransformed'; +const METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED = '{bucketInternalId}.files.imagesTransformed'; +const METRIC_BUCKET_ID_FILES = '{bucketInternalId}.files'; +const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage'; +const METRIC_SITES = 'sites'; +const METRIC_FUNCTIONS = 'functions'; +const METRIC_DEPLOYMENTS = 'deployments'; +const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage'; +const METRIC_BUILDS = 'builds'; +const METRIC_BUILDS_SUCCESS = 'builds.success'; +const METRIC_BUILDS_FAILED = 'builds.failed'; +const METRIC_BUILDS_STORAGE = 'builds.storage'; +const METRIC_BUILDS_COMPUTE = 'builds.compute'; +const METRIC_BUILDS_COMPUTE_SUCCESS = 'builds.compute.success'; +const METRIC_BUILDS_COMPUTE_FAILED = 'builds.compute.failed'; +const METRIC_BUILDS_MB_SECONDS = 'builds.mbSeconds'; +const METRIC_EXECUTIONS = 'executions'; +const METRIC_EXECUTIONS_COMPUTE = 'executions.compute'; +const METRIC_EXECUTIONS_MB_SECONDS = 'executions.mbSeconds'; +const METRIC_RESOURCE_TYPE_ID_EXECUTIONS = '{resourceType}.{resourceInternalId}.executions'; +const METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE = '{resourceType}.{resourceInternalId}.executions.compute'; +const METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS = '{resourceType}.{resourceInternalId}.executions.mbSeconds'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS = '{resourceType}.{resourceInternalId}.builds.success'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED = '{resourceType}.{resourceInternalId}.builds.failed'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE = '{resourceType}.{resourceInternalId}.builds.compute'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_SUCCESS = '{resourceType}.{resourceInternalId}.builds.compute.success'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_FAILED = '{resourceType}.{resourceInternalId}.builds.compute.failed'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS = '{resourceType}.{resourceInternalId}.builds.mbSeconds'; +const METRIC_RESOURCE_TYPE_ID_BUILDS = '{resourceType}.{resourceInternalId}.builds'; +const METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE = '{resourceType}.{resourceInternalId}.builds.storage'; +const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; +const METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; +const METRIC_RESOURCE_TYPE_EXECUTIONS = '{resourceType}.executions'; +const METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE = '{resourceType}.executions.compute'; +const METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS = '{resourceType}.executions.mbSeconds'; +const METRIC_RESOURCE_TYPE_BUILDS_SUCCESS = '{resourceType}.builds.success'; +const METRIC_RESOURCE_TYPE_BUILDS_FAILED = '{resourceType}.builds.failed'; +const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE = '{resourceType}.builds.compute'; +const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_SUCCESS = '{resourceType}.builds.compute.success'; +const METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_FAILED = '{resourceType}.builds.compute.failed'; +const METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS = '{resourceType}.builds.mbSeconds'; +const METRIC_RESOURCE_TYPE_BUILDS = '{resourceType}.builds'; +const METRIC_RESOURCE_TYPE_BUILDS_STORAGE = '{resourceType}.builds.storage'; +const METRIC_RESOURCE_TYPE_DEPLOYMENTS = '{resourceType}.deployments'; +const METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE = '{resourceType}.deployments.storage'; +const METRIC_NETWORK_REQUESTS = 'network.requests'; +const METRIC_NETWORK_INBOUND = 'network.inbound'; +const METRIC_NETWORK_OUTBOUND = 'network.outbound'; +const METRIC_MAU = 'users.mau'; +const METRIC_DAU = 'users.dau'; +const METRIC_WAU = 'users.wau'; +const METRIC_WEBHOOKS = 'webhooks'; +const METRIC_PLATFORMS = 'platforms'; +const METRIC_PROVIDERS = 'providers'; +const METRIC_TOPICS = 'topics'; +const METRIC_TARGETS = 'targets'; +const METRIC_PROVIDER_TYPE_TARGETS = '{providerType}.targets'; +const METRIC_KEYS = 'keys'; +const METRIC_DOMAINS = 'domains'; +const METRIC_SITES_REQUESTS = 'sites.requests'; +const METRIC_SITES_INBOUND = 'sites.inbound'; +const METRIC_SITES_OUTBOUND = 'sites.outbound'; +const METRIC_SITES_ID_REQUESTS = 'sites.{siteInternalId}.requests'; +const METRIC_SITES_ID_INBOUND = 'sites.{siteInternalId}.inbound'; +const METRIC_SITES_ID_OUTBOUND = 'sites.{siteInternalId}.outbound'; + +// Resource types + +const RESOURCE_TYPE_PROJECTS = 'projects'; +const RESOURCE_TYPE_FUNCTIONS = 'functions'; +const RESOURCE_TYPE_SITES = 'sites'; +const RESOURCE_TYPE_DATABASES = 'databases'; +const RESOURCE_TYPE_BUCKETS = 'buckets'; +const RESOURCE_TYPE_PROVIDERS = 'providers'; +const RESOURCE_TYPE_TOPICS = 'topics'; +const RESOURCE_TYPE_SUBSCRIBERS = 'subscribers'; +const RESOURCE_TYPE_MESSAGES = 'messages'; diff --git a/app/init/database/filters.php b/app/init/database/filters.php new file mode 100644 index 0000000000..933f291c0d --- /dev/null +++ b/app/init/database/filters.php @@ -0,0 +1,404 @@ +<?php + +use Appwrite\OpenSSL\OpenSSL; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\System\System; + +Database::addFilter( + 'casting', + function (mixed $value) { + return json_encode(['value' => $value], JSON_PRESERVE_ZERO_FRACTION); + }, + function (mixed $value) { + if (is_null($value)) { + return; + } + + return json_decode($value, true)['value']; + } +); + +Database::addFilter( + 'enum', + function (mixed $value, Document $attribute) { + if ($attribute->isSet('elements')) { + $attribute->removeAttribute('elements'); + } + + return $value; + }, + function (mixed $value, Document $attribute) { + $formatOptions = \json_decode($attribute->getAttribute('formatOptions', '[]'), true); + if (isset($formatOptions['elements'])) { + $attribute->setAttribute('elements', $formatOptions['elements']); + } + + return $value; + } +); + +Database::addFilter( + 'range', + function (mixed $value, Document $attribute) { + if ($attribute->isSet('min')) { + $attribute->removeAttribute('min'); + } + if ($attribute->isSet('max')) { + $attribute->removeAttribute('max'); + } + + return $value; + }, + function (mixed $value, Document $attribute) { + $formatOptions = json_decode($attribute->getAttribute('formatOptions', '[]'), true); + if (isset($formatOptions['min']) || isset($formatOptions['max'])) { + $attribute + ->setAttribute('min', $formatOptions['min']) + ->setAttribute('max', $formatOptions['max']); + } + + return $value; + } +); + +Database::addFilter( + 'subQueryAttributes', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + $attributes = $database->find('attributes', [ + Query::equal('collectionInternalId', [$document->getInternalId()]), + Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), + Query::limit($database->getLimitForAttributes()), + ]); + + 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'); + } + } + + return $attributes; + } +); + +Database::addFilter( + 'subQueryIndexes', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return $database + ->find('indexes', [ + Query::equal('collectionInternalId', [$document->getInternalId()]), + Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), + Query::limit($database->getLimitForIndexes()), + ]); + } +); + +Database::addFilter( + 'subQueryPlatforms', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return $database + ->find('platforms', [ + Query::equal('projectInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ]); + } +); + +Database::addFilter( + 'subQueryKeys', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return $database + ->find('keys', [ + Query::equal('projectInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ]); + } +); + +Database::addFilter( + 'subQueryWebhooks', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return $database + ->find('webhooks', [ + Query::equal('projectInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ]); + } +); + +Database::addFilter( + 'subQuerySessions', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return Authorization::skip(fn () => $database->find('sessions', [ + Query::equal('userInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ])); + } +); + +Database::addFilter( + 'subQueryTokens', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return Authorization::skip(fn () => $database + ->find('tokens', [ + Query::equal('userInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ])); + } +); + +Database::addFilter( + 'subQueryChallenges', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return Authorization::skip(fn () => $database + ->find('challenges', [ + Query::equal('userInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ])); + } +); + +Database::addFilter( + 'subQueryAuthenticators', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return Authorization::skip(fn () => $database + ->find('authenticators', [ + Query::equal('userInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ])); + } +); + +Database::addFilter( + 'subQueryMemberships', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return Authorization::skip(fn () => $database + ->find('memberships', [ + Query::equal('userInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY), + ])); + } +); + +Database::addFilter( + 'subQueryVariables', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return $database + ->find('variables', [ + Query::equal('resourceInternalId', [$document->getInternalId()]), + Query::equal('resourceType', ['function', 'site']), + Query::limit(APP_LIMIT_SUBQUERY), + ]); + } +); + +Database::addFilter( + 'encrypt', + function (mixed $value) { + $key = System::getEnv('_APP_OPENSSL_KEY_V1'); + $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); + $tag = null; + + return json_encode([ + 'data' => OpenSSL::encrypt($value, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag), + 'method' => OpenSSL::CIPHER_AES_128_GCM, + 'iv' => \bin2hex($iv), + 'tag' => \bin2hex($tag ?? ''), + 'version' => '1', + ]); + }, + function (mixed $value) { + if (is_null($value)) { + return; + } + $value = json_decode($value, true); + $key = System::getEnv('_APP_OPENSSL_KEY_V' . $value['version']); + + return OpenSSL::decrypt($value['data'], $value['method'], $key, 0, hex2bin($value['iv']), hex2bin($value['tag'])); + } +); + +Database::addFilter( + 'subQueryProjectVariables', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return $database + ->find('variables', [ + Query::equal('resourceType', ['project']), + Query::limit(APP_LIMIT_SUBQUERY) + ]); + } +); + +Database::addFilter( + 'userSearch', + function (mixed $value, Document $user) { + $searchValues = [ + $user->getId(), + $user->getAttribute('email', ''), + $user->getAttribute('name', ''), + $user->getAttribute('phone', '') + ]; + + foreach ($user->getAttribute('labels', []) as $label) { + $searchValues[] = 'label:' . $label; + } + + $search = implode(' ', \array_filter($searchValues)); + + return $search; + }, + function (mixed $value) { + return $value; + } +); + +Database::addFilter( + 'subQueryTargets', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + return Authorization::skip(fn () => $database + ->find('targets', [ + Query::equal('userInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBQUERY) + ])); + } +); + +Database::addFilter( + 'subQueryTopicTargets', + function (mixed $value) { + return; + }, + function (mixed $value, Document $document, Database $database) { + $targetIds = Authorization::skip(fn () => \array_map( + fn ($document) => $document->getAttribute('targetInternalId'), + $database->find('subscribers', [ + Query::equal('topicInternalId', [$document->getInternalId()]), + Query::limit(APP_LIMIT_SUBSCRIBERS_SUBQUERY) + ]) + )); + if (\count($targetIds) > 0) { + return $database->skipValidation(fn () => $database->find('targets', [ + Query::equal('$internalId', $targetIds) + ])); + } + return []; + } +); + +Database::addFilter( + 'providerSearch', + function (mixed $value, Document $provider) { + $searchValues = [ + $provider->getId(), + $provider->getAttribute('name', ''), + $provider->getAttribute('provider', ''), + $provider->getAttribute('type', '') + ]; + + $search = \implode(' ', \array_filter($searchValues)); + + return $search; + }, + function (mixed $value) { + return $value; + } +); + +Database::addFilter( + 'topicSearch', + function (mixed $value, Document $topic) { + $searchValues = [ + $topic->getId(), + $topic->getAttribute('name', ''), + $topic->getAttribute('description', ''), + ]; + + $search = \implode(' ', \array_filter($searchValues)); + + return $search; + }, + function (mixed $value) { + return $value; + } +); + +Database::addFilter( + 'messageSearch', + function (mixed $value, Document $message) { + $searchValues = [ + $message->getId(), + $message->getAttribute('description', ''), + $message->getAttribute('status', ''), + ]; + + $data = \json_decode($message->getAttribute('data', []), true); + $providerType = $message->getAttribute('providerType', ''); + + switch ($providerType) { + case MESSAGE_TYPE_EMAIL: + $searchValues[] = $data['subject']; + $searchValues[] = MESSAGE_TYPE_EMAIL; + break; + case MESSAGE_TYPE_SMS: + $searchValues[] = $data['content']; + $searchValues[] = MESSAGE_TYPE_SMS; + break; + case MESSAGE_TYPE_PUSH: + $searchValues[] = $data['title'] ?? ''; + $searchValues[] = MESSAGE_TYPE_PUSH; + break; + } + + $search = \implode(' ', \array_filter($searchValues)); + + return $search; + }, + function (mixed $value) { + return $value; + } +); diff --git a/app/init/database/formats.php b/app/init/database/formats.php new file mode 100644 index 0000000000..6c73877576 --- /dev/null +++ b/app/init/database/formats.php @@ -0,0 +1,43 @@ +<?php + +use Appwrite\Network\Validator\Email; +use Utopia\Database\Database; +use Utopia\Database\Validator\Datetime as DatetimeValidator; +use Utopia\Database\Validator\Structure; +use Utopia\Validator\IP; +use Utopia\Validator\Range; +use Utopia\Validator\URL; +use Utopia\Validator\WhiteList; + +Structure::addFormat(APP_DATABASE_ATTRIBUTE_EMAIL, function () { + return new Email(); +}, Database::VAR_STRING); + +Structure::addFormat(APP_DATABASE_ATTRIBUTE_DATETIME, function () { + return new DatetimeValidator(); +}, Database::VAR_DATETIME); + +Structure::addFormat(APP_DATABASE_ATTRIBUTE_ENUM, function ($attribute) { + $elements = $attribute['formatOptions']['elements'] ?? []; + return new WhiteList($elements, true); +}, Database::VAR_STRING); + +Structure::addFormat(APP_DATABASE_ATTRIBUTE_IP, function () { + return new IP(); +}, Database::VAR_STRING); + +Structure::addFormat(APP_DATABASE_ATTRIBUTE_URL, function () { + return new URL(); +}, Database::VAR_STRING); + +Structure::addFormat(APP_DATABASE_ATTRIBUTE_INT_RANGE, function ($attribute) { + $min = $attribute['formatOptions']['min'] ?? -INF; + $max = $attribute['formatOptions']['max'] ?? INF; + return new Range($min, $max, Range::TYPE_INTEGER); +}, Database::VAR_INTEGER); + +Structure::addFormat(APP_DATABASE_ATTRIBUTE_FLOAT_RANGE, function ($attribute) { + $min = $attribute['formatOptions']['min'] ?? -INF; + $max = $attribute['formatOptions']['max'] ?? INF; + return new Range($min, $max, Range::TYPE_FLOAT); +}, Database::VAR_FLOAT); diff --git a/app/init/locales.php b/app/init/locales.php new file mode 100644 index 0000000000..122dc89692 --- /dev/null +++ b/app/init/locales.php @@ -0,0 +1,23 @@ +<?php + +use Utopia\Config\Config; +use Utopia\Locale\Locale; + +Locale::$exceptions = false; + +$locales = Config::getParam('locale-codes', []); + +foreach ($locales as $locale) { + $code = $locale['code']; + + $path = __DIR__ . '/../config/locale/translations/' . $code . '.json'; + + if (!\file_exists($path)) { + $path = __DIR__ . '/../config/locale/translations/' . \substr($code, 0, 2) . '.json'; // if `ar-ae` doesn't exist, look for `ar` + if (!\file_exists($path)) { + $path = __DIR__ . '/../config/locale/translations/en.json'; // if none translation exists, use default from `en.json` + } + } + + Locale::setLanguageFromJSON($code, $path); +} diff --git a/app/init/registers.php b/app/init/registers.php new file mode 100644 index 0000000000..1ebcbc1691 --- /dev/null +++ b/app/init/registers.php @@ -0,0 +1,340 @@ +<?php + +use Appwrite\Extend\Exception; +use Appwrite\GraphQL\Promises\Adapter\Swoole; +use Appwrite\Hooks\Hooks; +use Appwrite\PubSub\Adapter\Redis as PubSub; +use Appwrite\URL\URL as AppwriteURL; +use MaxMind\Db\Reader; +use PHPMailer\PHPMailer\PHPMailer; +use Swoole\Database\PDOProxy; +use Utopia\App; +use Utopia\Cache\Adapter\Redis as RedisCache; +use Utopia\CLI\Console; +use Utopia\Config\Config; +use Utopia\Database\Adapter\MariaDB; +use Utopia\Database\Adapter\MySQL; +use Utopia\Database\Adapter\SQL; +use Utopia\Domains\Validator\PublicDomain; +use Utopia\DSN\DSN; +use Utopia\Logger\Adapter\AppSignal; +use Utopia\Logger\Adapter\LogOwl; +use Utopia\Logger\Adapter\Raygun; +use Utopia\Logger\Adapter\Sentry; +use Utopia\Logger\Logger; +use Utopia\Pools\Group; +use Utopia\Pools\Pool; +use Utopia\Queue; +use Utopia\Registry\Registry; +use Utopia\System\System; + +$register = new Registry(); + +App::setMode(System::getEnv('_APP_ENV', App::MODE_TYPE_PRODUCTION)); + +if (!App::isProduction()) { + // Allow specific domains to skip public domain validation in dev environment + // Useful for existing tests involving webhooks + PublicDomain::allow(['request-catcher']); +} +$register->set('logger', function () { + // Register error logger + $providerName = System::getEnv('_APP_LOGGING_PROVIDER', ''); + $providerConfig = System::getEnv('_APP_LOGGING_CONFIG', ''); + + if (empty($providerConfig)) { + return; + } + + try { + $loggingProvider = new DSN($providerConfig ?? ''); + + $providerName = $loggingProvider->getScheme(); + $providerConfig = match ($providerName) { + 'sentry' => ['key' => $loggingProvider->getPassword(), 'projectId' => $loggingProvider->getUser() ?? '', 'host' => 'https://' . $loggingProvider->getHost()], + 'logowl' => ['ticket' => $loggingProvider->getUser() ?? '', 'host' => $loggingProvider->getHost()], + default => ['key' => $loggingProvider->getHost()], + }; + } catch (Throwable $th) { + // Fallback for older Appwrite versions up to 1.5.x that use _APP_LOGGING_PROVIDER and _APP_LOGGING_CONFIG environment variables + Console::warning('Using deprecated logging configuration. Please update your configuration to use DSN format.' . $th->getMessage()); + $configChunks = \explode(";", $providerConfig); + + $providerConfig = match ($providerName) { + 'sentry' => [ 'key' => $configChunks[0], 'projectId' => $configChunks[1] ?? '', 'host' => '',], + 'logowl' => ['ticket' => $configChunks[0] ?? '', 'host' => ''], + default => ['key' => $providerConfig], + }; + } + + if (empty($providerName) || empty($providerConfig)) { + return; + } + + if (!Logger::hasProvider($providerName)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled"); + } + + try { + $adapter = match ($providerName) { + 'sentry' => new Sentry($providerConfig['projectId'], $providerConfig['key'], $providerConfig['host']), + 'logowl' => new LogOwl($providerConfig['ticket'], $providerConfig['host']), + 'raygun' => new Raygun($providerConfig['key']), + 'appsignal' => new AppSignal($providerConfig['key']), + default => null + }; + } catch (Throwable $th) { + $adapter = null; + } + + if ($adapter === null) { + Console::error("Logging provider not supported. Logging is disabled"); + return; + } + + return new Logger($adapter); +}); + +$register->set('pools', function () { + $group = new Group(); + + $fallbackForDB = 'db_main=' . AppwriteURL::unparse([ + 'scheme' => 'mariadb', + 'host' => System::getEnv('_APP_DB_HOST', 'mariadb'), + 'port' => System::getEnv('_APP_DB_PORT', '3306'), + 'user' => System::getEnv('_APP_DB_USER', ''), + 'pass' => System::getEnv('_APP_DB_PASS', ''), + 'path' => System::getEnv('_APP_DB_SCHEMA', ''), + ]); + $fallbackForRedis = 'redis_main=' . AppwriteURL::unparse([ + 'scheme' => 'redis', + 'host' => System::getEnv('_APP_REDIS_HOST', 'redis'), + 'port' => System::getEnv('_APP_REDIS_PORT', '6379'), + 'user' => System::getEnv('_APP_REDIS_USER', ''), + 'pass' => System::getEnv('_APP_REDIS_PASS', ''), + ]); + + $connections = [ + 'console' => [ + 'type' => 'database', + 'dsns' => $fallbackForDB, + 'multiple' => false, + 'schemes' => ['mariadb', 'mysql'], + ], + 'database' => [ + 'type' => 'database', + 'dsns' => $fallbackForDB, + 'multiple' => true, + 'schemes' => ['mariadb', 'mysql'], + ], + 'logs' => [ + 'type' => 'database', + 'dsns' => System::getEnv('_APP_CONNECTIONS_DB_LOGS', $fallbackForDB), + 'multiple' => false, + 'schemes' => ['mariadb', 'mysql'], + ], + 'publisher' => [ + 'type' => 'publisher', + 'dsns' => $fallbackForRedis, + 'multiple' => false, + 'schemes' => ['redis'], + ], + 'consumer' => [ + 'type' => 'consumer', + 'dsns' => $fallbackForRedis, + 'multiple' => false, + 'schemes' => ['redis'], + ], + 'pubsub' => [ + 'type' => 'pubsub', + 'dsns' => $fallbackForRedis, + 'multiple' => false, + 'schemes' => ['redis'], + ], + 'cache' => [ + 'type' => 'cache', + 'dsns' => $fallbackForRedis, + 'multiple' => true, + 'schemes' => ['redis'], + ], + ]; + + $maxConnections = System::getEnv('_APP_CONNECTIONS_MAX', 151); + $instanceConnections = $maxConnections / System::getEnv('_APP_POOL_CLIENTS', 14); + + $multiprocessing = System::getEnv('_APP_SERVER_MULTIPROCESS', 'disabled') === 'enabled'; + + if ($multiprocessing) { + $workerCount = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); + } else { + $workerCount = 1; + } + + if ($workerCount > $instanceConnections) { + throw new \Exception('Pool size is too small. Increase the number of allowed database connections or decrease the number of workers.', 500); + } + + $poolSize = (int)($instanceConnections / $workerCount); + + foreach ($connections as $key => $connection) { + $type = $connection['type'] ?? ''; + $multiple = $connection['multiple'] ?? false; + $schemes = $connection['schemes'] ?? []; + $config = []; + $dsns = explode(',', $connection['dsns'] ?? ''); + foreach ($dsns as &$dsn) { + $dsn = explode('=', $dsn); + $name = ($multiple) ? $key . '_' . $dsn[0] : $key; + $dsn = $dsn[1] ?? ''; + $config[] = $name; + if (empty($dsn)) { + //throw new Exception(Exception::GENERAL_SERVER_ERROR, "Missing value for DSN connection in {$key}"); + continue; + } + + $dsn = new DSN($dsn); + $dsnHost = $dsn->getHost(); + $dsnPort = $dsn->getPort(); + $dsnUser = $dsn->getUser(); + $dsnPass = $dsn->getPassword(); + $dsnScheme = $dsn->getScheme(); + $dsnDatabase = $dsn->getPath(); + + if (!in_array($dsnScheme, $schemes)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Invalid console database scheme"); + } + + /** + * Get Resource + * + * Creation could be reused across connection types like database, cache, queue, etc. + * + * Resource assignment to an adapter will happen below. + */ + $resource = match ($dsnScheme) { + '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( + 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) { + $redis = new \Redis(); + @$redis->pconnect($dsnHost, (int)$dsnPort); + if ($dsnPass) { + $redis->auth($dsnPass); + } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + + return $redis; + }, + default => throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid scheme'), + }; + + $pool = new Pool($name, $poolSize, function () use ($type, $resource, $dsn) { + // Get Adapter + switch ($type) { + case 'database': + $adapter = match ($dsn->getScheme()) { + 'mariadb' => new MariaDB($resource()), + 'mysql' => new MySQL($resource()), + default => null + }; + + $adapter->setDatabase($dsn->getPath()); + return $adapter; + case 'pubsub': + return match ($dsn->getScheme()) { + 'redis' => new PubSub($resource()), + default => null + }; + case 'publisher': + case 'consumer': + return match ($dsn->getScheme()) { + 'redis' => new Queue\Broker\Redis(new Queue\Connection\Redis($dsn->getHost(), $dsn->getPort())), + default => null + }; + case 'cache': + return match ($dsn->getScheme()) { + 'redis' => new RedisCache($resource()), + default => null + }; + default: + throw new Exception(Exception::GENERAL_SERVER_ERROR, "Server error: Missing adapter implementation."); + } + }); + + $group->add($pool); + } + + Config::setParam('pools-' . $key, $config); + } + + return $group; +}); + +$register->set('db', function () { + // This is usually for our workers or CLI commands scope + $dbHost = System::getEnv('_APP_DB_HOST', ''); + $dbPort = System::getEnv('_APP_DB_PORT', ''); + $dbUser = System::getEnv('_APP_DB_USER', ''); + $dbPass = System::getEnv('_APP_DB_PASS', ''); + $dbScheme = System::getEnv('_APP_DB_SCHEMA', ''); + + return new PDO( + "mysql:host={$dbHost};port={$dbPort};dbname={$dbScheme};charset=utf8mb4", + $dbUser, + $dbPass, + SQL::getPDOAttributes() + ); +}); + +$register->set('smtp', function () { + $mail = new PHPMailer(true); + + $mail->isSMTP(); + + $username = System::getEnv('_APP_SMTP_USERNAME'); + $password = System::getEnv('_APP_SMTP_PASSWORD'); + + $mail->XMailer = 'Appwrite Mailer'; + $mail->Host = System::getEnv('_APP_SMTP_HOST', 'smtp'); + $mail->Port = System::getEnv('_APP_SMTP_PORT', 25); + $mail->SMTPAuth = !empty($username) && !empty($password); + $mail->Username = $username; + $mail->Password = $password; + $mail->SMTPSecure = System::getEnv('_APP_SMTP_SECURE', ''); + $mail->SMTPAutoTLS = false; + $mail->CharSet = 'UTF-8'; + + $from = \urldecode(System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); + $email = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); + + $mail->setFrom($email, $from); + $mail->addReplyTo($email, $from); + + $mail->isHTML(true); + + return $mail; +}); +$register->set('geodb', function () { + return new Reader(__DIR__ . '/../assets/dbip/dbip-country-lite-2024-09.mmdb'); +}); +$register->set('passwordsDictionary', function () { + $content = \file_get_contents(__DIR__ . '/../assets/security/10k-common-passwords'); + $content = explode("\n", $content); + $content = array_flip($content); + return $content; +}); +$register->set('promiseAdapter', function () { + return new Swoole(); +}); +$register->set('hooks', function () { + return new Hooks(); +}); diff --git a/app/init/resources.php b/app/init/resources.php new file mode 100644 index 0000000000..1e6154df10 --- /dev/null +++ b/app/init/resources.php @@ -0,0 +1,854 @@ +<?php + +use Ahc\Jwt\JWT; +use Ahc\Jwt\JWTException; +use Appwrite\Auth\Auth; +use Appwrite\Auth\Key; +use Appwrite\Event\Audit; +use Appwrite\Event\Build; +use Appwrite\Event\Certificate; +use Appwrite\Event\Database as EventDatabase; +use Appwrite\Event\Delete; +use Appwrite\Event\Event; +use Appwrite\Event\Func; +use Appwrite\Event\Mail; +use Appwrite\Event\Messaging; +use Appwrite\Event\Migration; +use Appwrite\Event\Realtime; +use Appwrite\Event\StatsUsage; +use Appwrite\Event\Webhook; +use Appwrite\Extend\Exception; +use Appwrite\GraphQL\Schema; +use Appwrite\Network\Validator\Origin; +use Appwrite\Utopia\Request; +use Executor\Executor; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; +use Utopia\App; +use Utopia\Cache\Adapter\Sharding; +use Utopia\Cache\Cache; +use Utopia\CLI\Console; +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\DSN\DSN; +use Utopia\Locale\Locale; +use Utopia\Logger\Log; +use Utopia\Pools\Group; +use Utopia\Queue\Publisher; +use Utopia\Storage\Device; +use Utopia\Storage\Device\AWS; +use Utopia\Storage\Device\Backblaze; +use Utopia\Storage\Device\DOSpaces; +use Utopia\Storage\Device\Linode; +use Utopia\Storage\Device\Local; +use Utopia\Storage\Device\S3; +use Utopia\Storage\Device\Wasabi; +use Utopia\Storage\Storage; +use Utopia\System\System; +use Utopia\Validator\Hostname; +use Utopia\VCS\Adapter\Git\GitHub as VcsGitHub; + +// Runtime Execution +App::setResource('log', fn () => new Log()); +App::setResource('logger', function ($register) { + return $register->get('logger'); +}, ['register']); + +App::setResource('hooks', function ($register) { + return $register->get('hooks'); +}, ['register']); + +App::setResource('register', fn () => $register); +App::setResource('locale', fn () => new Locale(System::getEnv('_APP_LOCALE', 'en'))); + +App::setResource('localeCodes', function () { + return array_map(fn ($locale) => $locale['code'], Config::getParam('locale-codes', [])); +}); + +// Queues +App::setResource('publisher', function (Group $pools) { + return $pools->get('publisher')->pop()->getResource(); +}, ['pools']); +App::setResource('consumer', function (Group $pools) { + return $pools->get('consumer')->pop()->getResource(); +}, ['pools']); +App::setResource('queueForMessaging', function (Publisher $publisher) { + return new Messaging($publisher); +}, ['publisher']); +App::setResource('queueForMails', function (Publisher $publisher) { + return new Mail($publisher); +}, ['publisher']); +App::setResource('queueForBuilds', function (Publisher $publisher) { + return new Build($publisher); +}, ['publisher']); +App::setResource('queueForDatabase', function (Publisher $publisher) { + return new EventDatabase($publisher); +}, ['publisher']); +App::setResource('queueForDeletes', function (Publisher $publisher) { + return new Delete($publisher); +}, ['publisher']); +App::setResource('queueForEvents', function (Publisher $publisher) { + return new Event($publisher); +}, ['publisher']); +App::setResource('queueForWebhooks', function (Publisher $publisher) { + return new Webhook($publisher); +}, ['publisher']); +App::setResource('queueForRealtime', function () { + return new Realtime(); +}, []); +App::setResource('queueForStatsUsage', function (Publisher $publisher) { + return new StatsUsage($publisher); +}, ['publisher']); +App::setResource('queueForAudits', function (Publisher $publisher) { + return new Audit($publisher); +}, ['publisher']); +App::setResource('queueForFunctions', function (Publisher $publisher) { + return new Func($publisher); +}, ['publisher']); +App::setResource('queueForCertificates', function (Publisher $publisher) { + return new Certificate($publisher); +}, ['publisher']); +App::setResource('queueForMigrations', function (Publisher $publisher) { + return new Migration($publisher); +}, ['publisher']); +App::setResource('clients', function ($request, $console, $project) { + $console->setAttribute('platforms', [ // Always allow current host + '$collection' => ID::custom('platforms'), + 'name' => 'Current Host', + 'type' => Origin::CLIENT_TYPE_WEB, + 'hostname' => $request->getHostname(), + ], Document::SET_TYPE_APPEND); + + $hostnames = explode(',', System::getEnv('_APP_CONSOLE_HOSTNAMES', '')); + $validator = new Hostname(); + foreach ($hostnames as $hostname) { + $hostname = trim($hostname); + if (!$validator->isValid($hostname)) { + continue; + } + $console->setAttribute('platforms', [ + '$collection' => ID::custom('platforms'), + 'type' => Origin::CLIENT_TYPE_WEB, + 'name' => $hostname, + 'hostname' => $hostname, + ], Document::SET_TYPE_APPEND); + } + + /** + * Get All verified client URLs for both console and current projects + * + Filter for duplicated entries + */ + $clientsConsole = \array_map( + fn ($node) => $node['hostname'], + \array_filter( + $console->getAttribute('platforms', []), + fn ($node) => (isset($node['type']) && ($node['type'] === Origin::CLIENT_TYPE_WEB) && !empty($node['hostname'])) + ) + ); + + $clients = $clientsConsole; + $platforms = $project->getAttribute('platforms', []); + + foreach ($platforms as $node) { + if ( + isset($node['type']) && + ($node['type'] === Origin::CLIENT_TYPE_WEB || + $node['type'] === Origin::CLIENT_TYPE_FLUTTER_WEB) && + !empty($node['hostname']) + ) { + $clients[] = $node['hostname']; + } + } + + return \array_unique($clients); +}, ['request', 'console', 'project']); + +App::setResource('user', function ($mode, $project, $console, $request, $response, $dbForProject, $dbForPlatform) { + /** @var Appwrite\Utopia\Request $request */ + /** @var Appwrite\Utopia\Response $response */ + /** @var Utopia\Database\Document $project */ + /** @var Utopia\Database\Database $dbForProject */ + /** @var Utopia\Database\Database $dbForPlatform */ + /** @var string $mode */ + + Authorization::setDefaultStatus(true); + + Auth::setCookieName('a_session_' . $project->getId()); + + if (APP_MODE_ADMIN === $mode) { + Auth::setCookieName('a_session_' . $console->getId()); + } + + $session = Auth::decodeSession( + $request->getCookie( + Auth::$cookieName, // Get sessions + $request->getCookie(Auth::$cookieName . '_legacy', '') + ) + ); + + // Get session from header for SSR clients + if (empty($session['id']) && empty($session['secret'])) { + $sessionHeader = $request->getHeader('x-appwrite-session', ''); + + if (!empty($sessionHeader)) { + $session = Auth::decodeSession($sessionHeader); + } + } + + // Get fallback session from old clients (no SameSite support) or clients who block 3rd-party cookies + if ($response) { + $response->addHeader('X-Debug-Fallback', 'false'); + } + + if (empty($session['id']) && empty($session['secret'])) { + if ($response) { + $response->addHeader('X-Debug-Fallback', 'true'); + } + $fallback = $request->getHeader('x-fallback-cookies', ''); + $fallback = \json_decode($fallback, true); + $session = Auth::decodeSession(((isset($fallback[Auth::$cookieName])) ? $fallback[Auth::$cookieName] : '')); + } + + Auth::$unique = $session['id'] ?? ''; + Auth::$secret = $session['secret'] ?? ''; + + if (APP_MODE_ADMIN !== $mode) { + if ($project->isEmpty()) { + $user = new Document([]); + } else { + if ($project->getId() === 'console') { + $user = $dbForPlatform->getDocument('users', Auth::$unique); + } else { + $user = $dbForProject->getDocument('users', Auth::$unique); + } + } + } else { + $user = $dbForPlatform->getDocument('users', Auth::$unique); + } + + if ( + $user->isEmpty() // Check a document has been found in the DB + || !Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret) + ) { // Validate user has valid login token + $user = new Document([]); + } + + // if (APP_MODE_ADMIN === $mode) { + // if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) { + // Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users. + // } else { + // $user = new Document([]); + // } + // } + + $authJWT = $request->getHeader('x-appwrite-jwt', ''); + + if (!empty($authJWT) && !$project->isEmpty()) { // JWT authentication + $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 3600, 0); + + try { + $payload = $jwt->decode($authJWT); + } catch (JWTException $error) { + throw new Exception(Exception::USER_JWT_INVALID, 'Failed to verify JWT. ' . $error->getMessage()); + } + + $jwtUserId = $payload['userId'] ?? ''; + if (!empty($jwtUserId)) { + $user = $dbForProject->getDocument('users', $jwtUserId); + } + + $jwtSessionId = $payload['sessionId'] ?? ''; + if (!empty($jwtSessionId)) { + if (empty($user->find('$id', $jwtSessionId, 'sessions'))) { // Match JWT to active token + $user = new Document([]); + } + } + } + + $dbForProject->setMetadata('user', $user->getId()); + $dbForPlatform->setMetadata('user', $user->getId()); + + return $user; +}, ['mode', 'project', 'console', 'request', 'response', 'dbForProject', 'dbForPlatform']); + +App::setResource('project', function ($dbForPlatform, $request, $console) { + /** @var Appwrite\Utopia\Request $request */ + /** @var Utopia\Database\Database $dbForPlatform */ + /** @var Utopia\Database\Document $console */ + + $projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', '')); + + if (empty($projectId) || $projectId === 'console') { + return $console; + } + + $project = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $projectId)); + + return $project; +}, ['dbForPlatform', 'request', 'console']); + +App::setResource('session', function (Document $user) { + if ($user->isEmpty()) { + return; + } + + $sessions = $user->getAttribute('sessions', []); + $sessionId = Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret); + + if (!$sessionId) { + return; + } + + foreach ($sessions as $session) {/** @var Document $session */ + if ($sessionId === $session->getId()) { + return $session; + } + } + + return; +}, ['user']); + +App::setResource('console', function () { + return new Document(Config::getParam('console')); +}, []); + +App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform, Cache $cache, Document $project) { + if ($project->isEmpty() || $project->getId() === 'console') { + return $dbForPlatform; + } + + 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')); + } + + $dbAdapter = $pools + ->get($dsn->getHost()) + ->pop() + ->getResource(); + + $database = new Database($dbAdapter, $cache); + + $database + ->setMetadata('host', \gethostname()) + ->setMetadata('project', $project->getId()) + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); + + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { + $database + ->setSharedTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace($dsn->getParam('namespace')); + } else { + $database + ->setSharedTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } + + return $database; +}, ['pools', 'dbForPlatform', 'cache', 'project']); + +App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { + $dbAdapter = $pools + ->get('console') + ->pop() + ->getResource(); + + $database = new Database($dbAdapter, $cache); + + $database + ->setNamespace('_console') + ->setMetadata('host', \gethostname()) + ->setMetadata('project', 'console') + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); + + return $database; +}, ['pools', 'cache']); + +App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { + $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools + + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { + if ($project->isEmpty() || $project->getId() === 'console') { + return $dbForPlatform; + } + + 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')); + } + + $configure = (function (Database $database) use ($project, $dsn) { + $database + ->setMetadata('host', \gethostname()) + ->setMetadata('project', $project->getId()) + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); + + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { + $database + ->setSharedTables(true) + ->setTenant($project->getInternalId()) + ->setNamespace($dsn->getParam('namespace')); + } else { + $database + ->setSharedTables(false) + ->setTenant(null) + ->setNamespace('_' . $project->getInternalId()); + } + }); + + if (isset($databases[$dsn->getHost()])) { + $database = $databases[$dsn->getHost()]; + $configure($database); + return $database; + } + + $dbAdapter = $pools + ->get($dsn->getHost()) + ->pop() + ->getResource(); + + $database = new Database($dbAdapter, $cache); + $databases[$dsn->getHost()] = $database; + $configure($database); + + return $database; + }; +}, ['pools', 'dbForPlatform', 'cache']); + +App::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 + ); + + $database + ->setSharedTables(true) + ->setNamespace('logsV1') + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_API) + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); + + // set tenant + if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { + $database->setTenant($project->getInternalId()); + } + + return $database; + }; +}, ['pools', 'cache']); + +App::setResource('cache', function (Group $pools) { + $list = Config::getParam('pools-cache', []); + $adapters = []; + + foreach ($list as $value) { + $adapters[] = $pools + ->get($value) + ->pop() + ->getResource() + ; + } + + return new Cache(new Sharding($adapters)); +}, ['pools']); + +App::setResource('redis', function () { + $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); + $port = System::getEnv('_APP_REDIS_PORT', 6379); + $pass = System::getEnv('_APP_REDIS_PASS', ''); + + $redis = new \Redis(); + @$redis->pconnect($host, (int)$port); + if ($pass) { + $redis->auth($pass); + } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + + return $redis; +}); + +App::setResource('timelimit', function (\Redis $redis) { + return function (string $key, int $limit, int $time) use ($redis) { + return new TimeLimitRedis($key, $limit, $time, $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 (Document $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']); + +function getDevice(string $root, string $connection = ''): Device +{ + $connection = !empty($connection) ? $connection : System::getEnv('_APP_CONNECTIONS_STORAGE', ''); + + if (!empty($connection)) { + $acl = 'private'; + $device = Storage::DEVICE_LOCAL; + $accessKey = ''; + $accessSecret = ''; + $bucket = ''; + $region = ''; + $url = System::getEnv('_APP_STORAGE_S3_ENDPOINT', ''); + + try { + $dsn = new DSN($connection); + $device = $dsn->getScheme(); + $accessKey = $dsn->getUser() ?? ''; + $accessSecret = $dsn->getPassword() ?? ''; + $bucket = $dsn->getPath() ?? ''; + $region = $dsn->getParam('region'); + } catch (\Throwable $e) { + Console::warning($e->getMessage() . 'Invalid DSN. Defaulting to Local device.'); + } + + switch ($device) { + case Storage::DEVICE_S3: + if (!empty($url)) { + return new S3($root, $accessKey, $accessSecret, $url, $region, $acl); + } else { + return new AWS($root, $accessKey, $accessSecret, $bucket, $region, $acl); + } + // no break + case STORAGE::DEVICE_DO_SPACES: + $device = new DOSpaces($root, $accessKey, $accessSecret, $bucket, $region, $acl); + $device->setHttpVersion(S3::HTTP_VERSION_1_1); + return $device; + case Storage::DEVICE_BACKBLAZE: + return new Backblaze($root, $accessKey, $accessSecret, $bucket, $region, $acl); + case Storage::DEVICE_LINODE: + return new Linode($root, $accessKey, $accessSecret, $bucket, $region, $acl); + case Storage::DEVICE_WASABI: + return new Wasabi($root, $accessKey, $accessSecret, $bucket, $region, $acl); + case Storage::DEVICE_LOCAL: + default: + return new Local($root); + } + } else { + switch (strtolower(System::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) ?? '')) { + case Storage::DEVICE_LOCAL: + default: + return new Local($root); + case Storage::DEVICE_S3: + $s3AccessKey = System::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''); + $s3SecretKey = System::getEnv('_APP_STORAGE_S3_SECRET', ''); + $s3Region = System::getEnv('_APP_STORAGE_S3_REGION', ''); + $s3Bucket = System::getEnv('_APP_STORAGE_S3_BUCKET', ''); + $s3Acl = 'private'; + $s3EndpointUrl = System::getEnv('_APP_STORAGE_S3_ENDPOINT', ''); + if (!empty($s3EndpointUrl)) { + return new S3($root, $s3AccessKey, $s3SecretKey, $s3EndpointUrl, $s3Region, $s3Acl); + } else { + return new AWS($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl); + } + // no break + case Storage::DEVICE_DO_SPACES: + $doSpacesAccessKey = System::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', ''); + $doSpacesSecretKey = System::getEnv('_APP_STORAGE_DO_SPACES_SECRET', ''); + $doSpacesRegion = System::getEnv('_APP_STORAGE_DO_SPACES_REGION', ''); + $doSpacesBucket = System::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''); + $doSpacesAcl = 'private'; + $device = new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl); + $device->setHttpVersion(S3::HTTP_VERSION_1_1); + return $device; + case Storage::DEVICE_BACKBLAZE: + $backblazeAccessKey = System::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', ''); + $backblazeSecretKey = System::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', ''); + $backblazeRegion = System::getEnv('_APP_STORAGE_BACKBLAZE_REGION', ''); + $backblazeBucket = System::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', ''); + $backblazeAcl = 'private'; + return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl); + case Storage::DEVICE_LINODE: + $linodeAccessKey = System::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', ''); + $linodeSecretKey = System::getEnv('_APP_STORAGE_LINODE_SECRET', ''); + $linodeRegion = System::getEnv('_APP_STORAGE_LINODE_REGION', ''); + $linodeBucket = System::getEnv('_APP_STORAGE_LINODE_BUCKET', ''); + $linodeAcl = 'private'; + return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl); + case Storage::DEVICE_WASABI: + $wasabiAccessKey = System::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', ''); + $wasabiSecretKey = System::getEnv('_APP_STORAGE_WASABI_SECRET', ''); + $wasabiRegion = System::getEnv('_APP_STORAGE_WASABI_REGION', ''); + $wasabiBucket = System::getEnv('_APP_STORAGE_WASABI_BUCKET', ''); + $wasabiAcl = 'private'; + return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl); + } + } +} + +App::setResource('mode', function ($request) { + /** @var Appwrite\Utopia\Request $request */ + + /** + * Defines the mode for the request: + * - 'default' => Requests for Client and Server Side + * - 'admin' => Request from the Console on non-console projects + */ + return $request->getParam('mode', $request->getHeader('x-appwrite-mode', APP_MODE_DEFAULT)); +}, ['request']); + +App::setResource('geodb', function ($register) { + /** @var Utopia\Registry\Registry $register */ + return $register->get('geodb'); +}, ['register']); + +App::setResource('passwordsDictionary', function ($register) { + /** @var Utopia\Registry\Registry $register */ + return $register->get('passwordsDictionary'); +}, ['register']); + + +App::setResource('servers', function () { + $platforms = Config::getParam('platforms'); + $server = $platforms[APP_PLATFORM_SERVER]; + + $languages = array_map(function ($language) { + return strtolower($language['name']); + }, $server['sdks']); + + return $languages; +}); + +App::setResource('promiseAdapter', function ($register) { + return $register->get('promiseAdapter'); +}, ['register']); + +App::setResource('schema', function ($utopia, $dbForProject) { + + $complexity = function (int $complexity, array $args) { + $queries = Query::parseQueries($args['queries'] ?? []); + $query = Query::getByType($queries, [Query::TYPE_LIMIT])[0] ?? null; + $limit = $query ? $query->getValue() : APP_LIMIT_LIST_DEFAULT; + + return $complexity * $limit; + }; + + $attributes = function (int $limit, int $offset) use ($dbForProject) { + $attrs = Authorization::skip(fn () => $dbForProject->find('attributes', [ + Query::limit($limit), + Query::offset($offset), + ])); + + return \array_map(function ($attr) { + return $attr->getArrayCopy(); + }, $attrs); + }; + + $urls = [ + 'list' => function (string $databaseId, string $collectionId, array $args) { + return "/v1/databases/$databaseId/collections/$collectionId/documents"; + }, + 'create' => function (string $databaseId, string $collectionId, array $args) { + return "/v1/databases/$databaseId/collections/$collectionId/documents"; + }, + 'read' => function (string $databaseId, string $collectionId, array $args) { + return "/v1/databases/$databaseId/collections/$collectionId/documents/{$args['documentId']}"; + }, + 'update' => function (string $databaseId, string $collectionId, array $args) { + return "/v1/databases/$databaseId/collections/$collectionId/documents/{$args['documentId']}"; + }, + 'delete' => function (string $databaseId, string $collectionId, array $args) { + return "/v1/databases/$databaseId/collections/$collectionId/documents/{$args['documentId']}"; + }, + ]; + + $params = [ + 'list' => function (string $databaseId, string $collectionId, array $args) { + return [ 'queries' => $args['queries']]; + }, + 'create' => function (string $databaseId, string $collectionId, array $args) { + $id = $args['id'] ?? 'unique()'; + $permissions = $args['permissions'] ?? null; + + unset($args['id']); + unset($args['permissions']); + + // Order must be the same as the route params + return [ + 'databaseId' => $databaseId, + 'documentId' => $id, + 'collectionId' => $collectionId, + 'data' => $args, + 'permissions' => $permissions, + ]; + }, + 'update' => function (string $databaseId, string $collectionId, array $args) { + $documentId = $args['id']; + $permissions = $args['permissions'] ?? null; + + unset($args['id']); + unset($args['permissions']); + + // Order must be the same as the route params + return [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'documentId' => $documentId, + 'data' => $args, + 'permissions' => $permissions, + ]; + }, + ]; + + return Schema::build( + $utopia, + $complexity, + $attributes, + $urls, + $params, + ); +}, ['utopia', 'dbForProject']); + +App::setResource('contributors', function () { + $path = 'app/config/contributors.json'; + $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; + return $list; +}); + +App::setResource('employees', function () { + $path = 'app/config/employees.json'; + $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; + return $list; +}); + +App::setResource('heroes', function () { + $path = 'app/config/heroes.json'; + $list = (file_exists($path)) ? json_decode(file_get_contents($path), true) : []; + return $list; +}); + +App::setResource('gitHub', function (Cache $cache) { + return new VcsGitHub($cache); +}, ['cache']); + +App::setResource('requestTimestamp', function ($request) { + //TODO: Move this to the Request class itself + $timestampHeader = $request->getHeader('x-appwrite-timestamp'); + $requestTimestamp = null; + if (!empty($timestampHeader)) { + try { + $requestTimestamp = new \DateTime($timestampHeader); + } catch (\Throwable $e) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid X-Appwrite-Timestamp header value'); + } + } + return $requestTimestamp; +}, ['request']); + +App::setResource('plan', function (array $plan = []) { + return []; +}); + +App::setResource('smsRates', function () { + return []; +}); + +App::setResource('team', function (Document $project, Database $dbForPlatform, App $utopia, Request $request) { + $teamInternalId = ''; + if ($project->getId() !== 'console') { + $teamInternalId = $project->getAttribute('teamInternalId', ''); + } else { + $route = $utopia->match($request); + $path = $route->getPath(); + if (str_starts_with($path, '/v1/projects/:projectId')) { + $uri = $request->getURI(); + $pid = explode('/', $uri)[3]; + $p = Authorization::skip(fn () => $dbForPlatform->getDocument('projects', $pid)); + $teamInternalId = $p->getAttribute('teamInternalId', ''); + } elseif ($path === '/v1/projects') { + $teamId = $request->getParam('teamId', ''); + $team = Authorization::skip(fn () => $dbForPlatform->getDocument('teams', $teamId)); + return $team; + } + } + + $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { + return $dbForPlatform->findOne('teams', [ + Query::equal('$internalId', [$teamInternalId]), + ]); + }); + + return $team; +}, ['project', 'dbForPlatform', 'utopia', 'request']); + +App::setResource( + 'isResourceBlocked', + fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false +); + +App::setResource('previewHostname', function (Request $request, ?Key $apiKey) { + $allowed = false; + + if (App::isDevelopment()) { + $allowed = true; + } elseif (!\is_null($apiKey) && $apiKey->getHostnameOverride() === true) { + $allowed = true; + } + + if ($allowed) { + $host = $request->getQuery('appwrite-hostname', $request->getHeader('x-appwrite-hostname', '')) ?? ''; + if (!empty($host)) { + return $host; + } + } + + return ''; +}, ['request', 'apiKey']); + +App::setResource('apiKey', function (Request $request, Document $project): ?Key { + $key = $request->getHeader('x-appwrite-key'); + + if (empty($key)) { + return null; + } + + return Key::decode($project, $key); +}, ['request', 'project']); + +App::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST'))); diff --git a/app/realtime.php b/app/realtime.php index 48979817c4..86f9c85fdd 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -13,7 +13,7 @@ use Swoole\Runtime; use Swoole\Table; use Swoole\Timer; use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\App; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; @@ -29,6 +29,7 @@ use Utopia\Database\Validator\Authorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\System\System; +use Utopia\Telemetry\Adapter\None as NoTelemetry; use Utopia\WebSocket\Adapter; use Utopia\WebSocket\Server; @@ -92,7 +93,9 @@ if (!function_exists('getProjectDB')) { $database = new Database($adapter, getCache()); - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) @@ -135,6 +138,32 @@ if (!function_exists('getCache')) { } } +// Allows overriding +if (!function_exists('getRedis')) { + function getRedis(): \Redis + { + $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); + $port = System::getEnv('_APP_REDIS_PORT', 6379); + $pass = System::getEnv('_APP_REDIS_PASS', ''); + + $redis = new \Redis(); + @$redis->pconnect($host, (int)$port); + if ($pass) { + $redis->auth($pass); + } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + + return $redis; + } +} + +if (!function_exists('getTimelimit')) { + function getTimelimit(): TimeLimitRedis + { + return new TimeLimitRedis("", 0, 1, getRedis()); + } +} + if (!function_exists('getRealtime')) { function getRealtime(): Realtime { @@ -142,6 +171,13 @@ if (!function_exists('getRealtime')) { } } +if (!function_exists('getTelemetry')) { + function getTelemetry(int $workerId): Utopia\Telemetry\Adapter + { + return new NoTelemetry(); + } +} + $realtime = getRealtime(); /** @@ -157,7 +193,7 @@ $stats->create(); $containerId = uniqid(); $statsDocument = null; -$workerNumber = swoole_cpu_num() * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); +$workerNumber = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intval(System::getEnv('_APP_WORKER_PER_CORE', 6)); $adapter = new Adapter\Swoole(port: System::getEnv('PORT', 80)); $adapter @@ -174,7 +210,7 @@ $logError = function (Throwable $error, string $action) use ($register) { $log = new Log(); $log->setNamespace("realtime"); - $log->setServer(gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); @@ -274,6 +310,12 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $realtime, $logError) { Console::success('Worker ' . $workerId . ' started successfully'); + $telemetry = getTelemetry($workerId); + $register->set('telemetry', fn () => $telemetry); + $register->set('telemetry.connectionCounter', fn () => $telemetry->createUpDownCounter('realtime.server.open_connections')); + $register->set('telemetry.connectionCreatedCounter', fn () => $telemetry->createCounter('realtime.server.connection.created')); + $register->set('telemetry.messageSentCounter', fn () => $telemetry->createCounter('realtime.server.message.sent')); + $attempts = 0; $start = time(); @@ -416,6 +458,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, ); if (($num = count($receivers)) > 0) { + $register->get('telemetry.messageSentCounter')->add($num); $stats->incr($event['project'], 'messages', $num); } }); @@ -464,7 +507,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, throw new AppwriteException(AppwriteException::GENERAL_API_DISABLED); } - $dbForProject = getProjectDB($project); + $timelimit = $app->getResource('timelimit'); $console = $app->getResource('console'); /** @var Document $console */ $user = $app->getResource('user'); /** @var Document $user */ @@ -473,12 +516,12 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, * * Abuse limits are connecting 128 times per minute and ip address. */ - $timeLimit = new TimeLimit('url:{url},ip:{ip}', 128, 60, $dbForProject); - $timeLimit + $timelimit = $timelimit('url:{url},ip:{ip}', 128, 60); + $timelimit ->setParam('{ip}', $request->getIP()) ->setParam('{url}', $request->getURI()); - $abuse = new Abuse($timeLimit); + $abuse = new Abuse($timelimit); if (System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') === 'enabled' && $abuse->check()) { throw new Exception(Exception::REALTIME_TOO_MANY_MESSAGES, 'Too many requests'); @@ -519,6 +562,9 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, ] ])); + $register->get('telemetry.connectionCounter')->add(1); + $register->get('telemetry.connectionCreatedCounter')->add(1); + $stats->set($project->getId(), [ 'projectId' => $project->getId(), 'teamId' => $project->getAttribute('teamId') @@ -573,7 +619,7 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re * * Abuse limits are sending 32 times per minute and connection. */ - $timeLimit = new TimeLimit('url:{url},connection:{connection}', 32, 60, $database); + $timeLimit = getTimelimit('url:{url},connection:{connection}', 32, 60); $timeLimit ->setParam('{connection}', $connection) @@ -655,9 +701,10 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re } }); -$server->onClose(function (int $connection) use ($realtime, $stats) { +$server->onClose(function (int $connection) use ($realtime, $stats, $register) { if (array_key_exists($connection, $realtime->connections)) { $stats->decr($realtime->connections[$connection]['projectId'], 'connectionsTotal'); + $register->get('telemetry.connectionCounter')->add(-1); } $realtime->unsubscribe($connection); diff --git a/app/views/general/404.phtml b/app/views/general/404.phtml new file mode 100644 index 0000000000..5e63344c8a --- /dev/null +++ b/app/views/general/404.phtml @@ -0,0 +1,187 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>404 Not Found + + + + + +
+
+
Page not found
+

The page you’re looking for doesn’t exist.

+ +
+
+ +
+

Powered by

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/app/views/general/error.phtml b/app/views/general/error.phtml index a3715e0156..60afe86494 100644 --- a/app/views/general/error.phtml +++ b/app/views/general/error.phtml @@ -2,21 +2,98 @@ $development = $this->getParam('development', false); $type = $this->getParam('type', 'general_server_error'); $code = $this->getParam('code', 500); -$errorID = $this->getParam('errorID', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); $message = $this->getParam('message', ''); $trace = $this->getParam('trace', []); -$projectName = $this->getParam('projectName', ''); -$projectURL = $this->getParam('projectURL', ''); -$title = $this->getParam('title', '') +$title = $this->getParam('title', 'Error'); +$exception = $this->getParam('exception', null); + +$isSimpleMessage = true; +$label = ''; +$labelClass = ''; +$buttons = []; + +if($exception !== null && method_exists($exception, 'getCTAs')) { + foreach ($exception->getCTAs() as $index => $cta) { + $class = ($index === 0) ? 'bordered-button' : 'button'; + + $buttons[] = [ + 'text' => $cta['label'], + 'url' => $cta['url'], + 'class' => $class + ]; + } +} + +switch ($type) { + case 'proxy_error_override': + $type = ''; + $label = 'Error ' . $code; + + $message = $code >= 500 ? 'An unexpected server error occured.' : 'An unexpected client error occured.'; + switch($code) { + case 401: + $message = 'You must sign in to access this page.'; + break; + case 403: + $message = 'You are not authorized to access this page.'; + break; + case 404: + $message = 'The page you are looking for does not exist.'; + break; + case 504: + $message = 'The server did not respond in time.'; + break; + case 501: + $message = 'This page is not implemented yet.'; + break; + } + + break; + case 'function_execute_permission_missing': + $label = 'Execution not permitted'; + $labelClass = 'warning'; + break; + case 'build_not_ready': + $label = 'Deployment is still building'; + $message = 'The page will update after the build completes.'; + $labelClass = 'warning'; + break; + case 'build_failed': + $label = 'Deployment build failed'; + $message = 'An error occurred during the build process.'; + $labelClass = 'error'; + break; + case 'rule_not_found': + $label = 'Nothing is here yet'; + $message = 'This page is empty, but you can make it yours.'; + break; + case 'deployment_not_found': + $label = 'No active deployments'; + $message = 'This page is empty, activate a deployment to make it live.'; + break; + case 'build_canceled': + $label = 'Deployment build canceled'; + $message = 'This build was canceled and won\'t be deployed.'; + break; + case 'general_route_not_found': + $label = 'Page not found'; + $message = 'The page you\'re looking for doesn\'t exist.'; + break; + default: + $label = 'Error ' . $code; + $message = $message; + $isSimpleMessage = false; + break; +} ?> - - - + + + getParam('title', '') as="font" type="font/woff2" crossorigin /> - - - - - - - - - - <?php echo $this->print($title); ?> - -
-
-
-

Error print($code); ?>

-

print($message); ?>

-
-

Type

-

print($type); ?>

+ +
+
+
print($label); ?>
+

print($message); ?>

+ +
+ print($type); ?>
- -

Error Trace

- -
-
- - - $value) : ?> - - - - - - - -
print($key, self::FILTER_ESCAPE); ?> - - -
print(var_export($value, true), self::FILTER_ESCAPE); ?>
- -
print($value, self::FILTER_ESCAPE); ?>
- -
-
-
-
+ +
+ + + + + + + + +
-
+
+ +
+ +
Error trace
+ $traceItem): ?> +
+ +
file
+
print($traceItem['file']); ?>
+ + + +
line
+
print($traceItem['line']); ?>
+ + + +
function
+
print($traceItem['function']); ?>
+ + + +
args
+
print(\var_export($traceItem['args'], true)); ?>
+ +
+ +
+ + +
+

Powered by

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
- \ No newline at end of file diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 8d7fecb479..1311217238 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -65,6 +65,8 @@ $image = $this->getParam('image', ''); - appwrite-config:/storage/config:rw - appwrite-certificates:/storage/certificates:rw - appwrite-functions:/storage/functions:rw + - appwrite-sites:/storage/sites:rw + - appwrite-builds:/storage/builds:rw depends_on: - mariadb - redis @@ -86,10 +88,12 @@ $image = $this->getParam('image', ''); - _APP_OPTIONS_ABUSE - _APP_OPTIONS_ROUTER_PROTECTION - _APP_OPTIONS_FORCE_HTTPS - - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS + - _APP_OPTIONS_ROUTER_FORCE_HTTPS - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - - _APP_DOMAIN_TARGET + - _APP_DOMAIN_TARGET_CNAME + - _APP_DOMAIN_TARGET_AAAA + - _APP_DOMAIN_TARGET_A - _APP_DOMAIN_FUNCTIONS - _APP_REDIS_HOST - _APP_REDIS_PORT @@ -116,6 +120,7 @@ $image = $this->getParam('image', ''); - _APP_STORAGE_S3_SECRET - _APP_STORAGE_S3_REGION - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_S3_ENDPOINT - _APP_STORAGE_DO_SPACES_ACCESS_KEY - _APP_STORAGE_DO_SPACES_SECRET - _APP_STORAGE_DO_SPACES_REGION @@ -132,12 +137,15 @@ $image = $this->getParam('image', ''); - _APP_STORAGE_WASABI_SECRET - _APP_STORAGE_WASABI_REGION - _APP_STORAGE_WASABI_BUCKET - - _APP_FUNCTIONS_SIZE_LIMIT + - _APP_COMPUTE_SIZE_LIMIT - _APP_FUNCTIONS_TIMEOUT - - _APP_FUNCTIONS_BUILD_TIMEOUT - - _APP_FUNCTIONS_CPUS - - _APP_FUNCTIONS_MEMORY + - _APP_SITES_TIMEOUT + - _APP_COMPUTE_BUILD_TIMEOUT + - _APP_COMPUTE_CPUS + - _APP_COMPUTE_MEMORY - _APP_FUNCTIONS_RUNTIMES + - _APP_SITES_RUNTIMES + - _APP_DOMAIN_SITES - _APP_EXECUTOR_SECRET - _APP_EXECUTOR_HOST - _APP_LOGGING_CONFIG @@ -147,6 +155,7 @@ $image = $this->getParam('image', ''); - _APP_MAINTENANCE_RETENTION_CACHE - _APP_MAINTENANCE_RETENTION_ABUSE - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY - _APP_MAINTENANCE_RETENTION_SCHEDULES - _APP_SMS_PROVIDER @@ -163,11 +172,10 @@ $image = $this->getParam('image', ''); - _APP_MIGRATIONS_FIREBASE_CLIENT_ID - _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET - _APP_ASSISTANT_OPENAI_API_KEY - appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:5.0.12 + image: /console:5.2.53 restart: unless-stopped networks: - appwrite @@ -298,6 +306,7 @@ $image = $this->getParam('image', ''); - appwrite-uploads:/storage/uploads:rw - appwrite-cache:/storage/cache:rw - appwrite-functions:/storage/functions:rw + - appwrite-sites:/storage/sites:rw - appwrite-builds:/storage/builds:rw - appwrite-certificates:/storage/certificates:rw environment: @@ -318,6 +327,7 @@ $image = $this->getParam('image', ''); - _APP_STORAGE_S3_SECRET - _APP_STORAGE_S3_REGION - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_S3_ENDPOINT - _APP_STORAGE_DO_SPACES_ACCESS_KEY - _APP_STORAGE_DO_SPACES_SECRET - _APP_STORAGE_DO_SPACES_REGION @@ -339,7 +349,10 @@ $image = $this->getParam('image', ''); - _APP_EXECUTOR_HOST - _APP_MAINTENANCE_RETENTION_ABUSE - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE - _APP_MAINTENANCE_RETENTION_EXECUTION + - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_EMAIL_CERTIFICATES appwrite-worker-databases: image: /: @@ -380,7 +393,9 @@ $image = $this->getParam('image', ''); - mariadb volumes: - appwrite-functions:/storage/functions:rw + - appwrite-sites:/storage/sites:rw - appwrite-builds:/storage/builds:rw + - appwrite-uploads:/storage/uploads:rw environment: - _APP_ENV - _APP_WORKER_PER_CORE @@ -401,18 +416,20 @@ $image = $this->getParam('image', ''); - _APP_VCS_GITHUB_PRIVATE_KEY - _APP_VCS_GITHUB_APP_ID - _APP_FUNCTIONS_TIMEOUT - - _APP_FUNCTIONS_BUILD_TIMEOUT - - _APP_FUNCTIONS_CPUS - - _APP_FUNCTIONS_MEMORY - - _APP_FUNCTIONS_SIZE_LIMIT + - _APP_SITES_TIMEOUT + - _APP_COMPUTE_BUILD_TIMEOUT + - _APP_COMPUTE_CPUS + - _APP_COMPUTE_MEMORY + - _APP_COMPUTE_SIZE_LIMIT - _APP_OPTIONS_FORCE_HTTPS - - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS + - _APP_OPTIONS_ROUTER_FORCE_HTTPS - _APP_DOMAIN - _APP_STORAGE_DEVICE - _APP_STORAGE_S3_ACCESS_KEY - _APP_STORAGE_S3_SECRET - _APP_STORAGE_S3_REGION - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_S3_ENDPOINT - _APP_STORAGE_DO_SPACES_ACCESS_KEY - _APP_STORAGE_DO_SPACES_SECRET - _APP_STORAGE_DO_SPACES_REGION @@ -429,6 +446,7 @@ $image = $this->getParam('image', ''); - _APP_STORAGE_WASABI_SECRET - _APP_STORAGE_WASABI_REGION - _APP_STORAGE_WASABI_BUCKET + - _APP_DOMAIN_SITES appwrite-worker-certificates: image: /: @@ -449,7 +467,9 @@ $image = $this->getParam('image', ''); - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - - _APP_DOMAIN_TARGET + - _APP_DOMAIN_TARGET_CNAME + - _APP_DOMAIN_TARGET_AAAA + - _APP_DOMAIN_TARGET_A - _APP_DOMAIN_FUNCTIONS - _APP_EMAIL_CERTIFICATES - _APP_REDIS_HOST @@ -491,9 +511,10 @@ $image = $this->getParam('image', ''); - _APP_DB_USER - _APP_DB_PASS - _APP_FUNCTIONS_TIMEOUT - - _APP_FUNCTIONS_BUILD_TIMEOUT - - _APP_FUNCTIONS_CPUS - - _APP_FUNCTIONS_MEMORY + - _APP_SITES_TIMEOUT + - _APP_COMPUTE_BUILD_TIMEOUT + - _APP_COMPUTE_CPUS + - _APP_COMPUTE_MEMORY - _APP_EXECUTOR_SECRET - _APP_EXECUTOR_HOST - _APP_USAGE_STATS @@ -568,6 +589,7 @@ $image = $this->getParam('image', ''); - _APP_STORAGE_S3_SECRET - _APP_STORAGE_S3_REGION - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_S3_ENDPOINT - _APP_STORAGE_DO_SPACES_ACCESS_KEY - _APP_STORAGE_DO_SPACES_SECRET - _APP_STORAGE_DO_SPACES_REGION @@ -600,7 +622,9 @@ $image = $this->getParam('image', ''); - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - - _APP_DOMAIN_TARGET + - _APP_DOMAIN_TARGET_CNAME + - _APP_DOMAIN_TARGET_AAAA + - _APP_DOMAIN_TARGET_A - _APP_EMAIL_SECURITY - _APP_REDIS_HOST - _APP_REDIS_PORT @@ -629,7 +653,9 @@ $image = $this->getParam('image', ''); - _APP_ENV - _APP_WORKER_PER_CORE - _APP_DOMAIN - - _APP_DOMAIN_TARGET + - _APP_DOMAIN_TARGET_CNAME + - _APP_DOMAIN_TARGET_AAAA + - _APP_DOMAIN_TARGET_A - _APP_DOMAIN_FUNCTIONS - _APP_OPENSSL_KEY_V1 - _APP_REDIS_HOST @@ -646,13 +672,73 @@ $image = $this->getParam('image', ''); - _APP_MAINTENANCE_RETENTION_CACHE - _APP_MAINTENANCE_RETENTION_ABUSE - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY - _APP_MAINTENANCE_RETENTION_SCHEDULES - appwrite-worker-usage: + appwrite-task-stats-resources: image: /: - entrypoint: worker-usage - container_name: appwrite-worker-usage + container_name: appwrite-task-stats-resources + entrypoint: stats-resources + <<: *x-logging + networks: + - appwrite + volumes: + - ./app:/usr/src/code/app + - ./src:/usr/src/code/src + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_USAGE_STATS + - _APP_LOGGING_CONFIG + - _APP_DATABASE_SHARED_TABLES + - _APP_STATS_RESOURCES_INTERVAL + + appwrite-worker-stats-resources: + image: /: + entrypoint: worker-stats-resources + container_name: appwrite-worker-stats-resources + <<: *x-logging + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_USAGE_STATS + - _APP_LOGGING_CONFIG + - _APP_STATS_RESOURCES_INTERVAL + + appwrite-worker-stats-usage: + image: /: + entrypoint: worker-stats-usage + container_name: appwrite-worker-stats-usage <<: *x-logging restart: unless-stopped networks: @@ -677,11 +763,11 @@ $image = $this->getParam('image', ''); - _APP_LOGGING_CONFIG - _APP_USAGE_AGGREGATION_INTERVAL - appwrite-worker-usage-dump: + appwrite-worker-stats-usage-dump: image: /: - entrypoint: worker-usage-dump + entrypoint: worker-stats-usage-dump <<: *x-logging - container_name: appwrite-worker-usage-dump + container_name: appwrite-worker-stats-usage-dump restart: unless-stopped networks: - appwrite @@ -789,6 +875,14 @@ $image = $this->getParam('image', ''); - appwrite environment: - _APP_ASSISTANT_OPENAI_API_KEY + + appwrite-browser: + image: appwrite/browser:0.2.2 + container_name: appwrite-browser + <<: *x-logging + restart: unless-stopped + networks: + - appwrite openruntimes-executor: container_name: openruntimes-executor @@ -796,7 +890,7 @@ $image = $this->getParam('image', ''); <<: *x-logging restart: unless-stopped stop_signal: SIGINT - image: openruntimes/executor:0.6.11 + image: openruntimes/executor:0.7.13 networks: - appwrite - runtimes @@ -804,24 +898,27 @@ $image = $this->getParam('image', ''); - /var/run/docker.sock:/var/run/docker.sock - appwrite-builds:/storage/builds:rw - appwrite-functions:/storage/functions:rw + - appwrite-sites:/storage/sites:rw # Host mount nessessary to share files between executor and runtimes. # It's not possible to share mount file between 2 containers without host mount (copying is too slow) - /tmp:/tmp:rw environment: - - OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD - - OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL - - OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK + - OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_COMPUTE_INACTIVE_THRESHOLD + - OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_COMPUTE_MAINTENANCE_INTERVAL + - OPR_EXECUTOR_NETWORK=$_APP_COMPUTE_RUNTIMES_NETWORK - OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME - OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD - OPR_EXECUTOR_ENV=$_APP_ENV - - OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES + - OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES,$_APP_SITES_RUNTIMES - OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET + - OPR_EXECUTOR_RUNTIME_VERSIONS=v5 - OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG - OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE - OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY - OPR_EXECUTOR_STORAGE_S3_SECRET=$_APP_STORAGE_S3_SECRET - OPR_EXECUTOR_STORAGE_S3_REGION=$_APP_STORAGE_S3_REGION - OPR_EXECUTOR_STORAGE_S3_BUCKET=$_APP_STORAGE_S3_BUCKET + - OPR_EXECUTOR_STORAGE_S3_ENDPOINT=$_APP_STORAGE_S3_ENDPOINT - OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=$_APP_STORAGE_DO_SPACES_ACCESS_KEY - OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=$_APP_STORAGE_DO_SPACES_SECRET - OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=$_APP_STORAGE_DO_SPACES_REGION @@ -895,5 +992,6 @@ volumes: appwrite-uploads: appwrite-certificates: appwrite-functions: + appwrite-sites: appwrite-builds: appwrite-config: diff --git a/app/worker.php b/app/worker.php index 4741afe7ea..3dfabfed57 100644 --- a/app/worker.php +++ b/app/worker.php @@ -2,6 +2,7 @@ require_once __DIR__ . '/init.php'; +use Appwrite\Certificates\LetsEncrypt; use Appwrite\Event\Audit; use Appwrite\Event\Build; use Appwrite\Event\Certificate; @@ -12,11 +13,14 @@ use Appwrite\Event\Func; use Appwrite\Event\Mail; use Appwrite\Event\Messaging; use Appwrite\Event\Migration; -use Appwrite\Event\Usage; -use Appwrite\Event\UsageDump; +use Appwrite\Event\Realtime; +use Appwrite\Event\StatsUsage; +use Appwrite\Event\StatsUsageDump; +use Appwrite\Event\Webhook; use Appwrite\Platform\Appwrite; +use Executor\Executor; use Swoole\Runtime; -use Utopia\App; +use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; @@ -30,8 +34,8 @@ use Utopia\Logger\Log; use Utopia\Logger\Logger; use Utopia\Platform\Service; use Utopia\Pools\Group; -use Utopia\Queue\Connection; use Utopia\Queue\Message; +use Utopia\Queue\Publisher; use Utopia\Queue\Server; use Utopia\Registry\Registry; use Utopia\System\System; @@ -41,7 +45,7 @@ Runtime::enableCoroutine(SWOOLE_HOOK_ALL); Server::setResource('register', fn () => $register); -Server::setResource('dbForConsole', function (Cache $cache, Registry $register) { +Server::setResource('dbForPlatform', function (Cache $cache, Registry $register) { $pools = $register->get('pools'); $database = $pools ->get('console') @@ -54,7 +58,7 @@ Server::setResource('dbForConsole', function (Cache $cache, Registry $register) return $adapter; }, ['cache', 'register']); -Server::setResource('project', function (Message $message, Database $dbForConsole) { +Server::setResource('project', function (Message $message, Database $dbForPlatform) { $payload = $message->getPayload() ?? []; $project = new Document($payload['project'] ?? []); @@ -62,12 +66,12 @@ Server::setResource('project', function (Message $message, Database $dbForConsol return $project; } - return $dbForConsole->getDocument('projects', $project->getId()); -}, ['message', 'dbForConsole']); + return $dbForPlatform->getDocument('projects', $project->getId()); +}, ['message', 'dbForPlatform']); -Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForConsole) { +Server::setResource('dbForProject', function (Cache $cache, Registry $register, Message $message, Document $project, Database $dbForPlatform) { if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; + return $dbForPlatform; } $pools = $register->get('pools'); @@ -93,7 +97,9 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) @@ -105,15 +111,17 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, ->setNamespace('_' . $project->getInternalId()); } - return $database; -}, ['cache', 'register', 'message', 'project', 'dbForConsole']); + $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); -Server::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $cache) { + return $database; +}, ['cache', 'register', 'message', 'project', 'dbForPlatform']); + +Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools - return function (Document $project) use ($pools, $dbForConsole, $cache, &$databases): Database { + return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases): Database { if ($project->isEmpty() || $project->getId() === 'console') { - return $dbForConsole; + return $dbForPlatform; } try { @@ -126,7 +134,9 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso if (isset($databases[$dsn->getHost()])) { $database = $databases[$dsn->getHost()]; - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) @@ -150,7 +160,9 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $databases[$dsn->getHost()] = $database; - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + + if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) @@ -162,20 +174,58 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso ->setNamespace('_' . $project->getInternalId()); } + $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); + return $database; }; -}, ['pools', 'dbForConsole', 'cache']); +}, ['pools', 'dbForPlatform', 'cache']); + +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()); + return $database; + } + + $dbAdapter = $pools + ->get('logs') + ->pop() + ->getResource(); + + $database = new Database( + $dbAdapter, + $cache + ); + + $database + ->setSharedTables(true) + ->setNamespace('logsV1') + ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER) + ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); + + // set tenant + if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { + $database->setTenant($project->getInternalId()); + } + + return $database; + }; +}, ['pools', 'cache']); Server::setResource('abuseRetention', function () { - return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400)); + return time() - (int) System::getEnv('_APP_MAINTENANCE_RETENTION_ABUSE', 86400); // 1 day }); -Server::setResource('auditRetention', function () { - return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 1209600)); -}); +Server::setResource('auditRetention', function (Document $project) { + if ($project->getId() === 'console') { + return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE', 15778800)); // 6 months + } + return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_AUDIT', 1209600)); // 14 days +}, ['project']); Server::setResource('executionRetention', function () { - return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_EXECUTION', 1209600)); + return DateTime::addSeconds(new \DateTime(), -1 * System::getEnv('_APP_MAINTENANCE_RETENTION_EXECUTION', 1209600)); // 14 days }); Server::setResource('cache', function (Registry $register) { @@ -194,59 +244,92 @@ Server::setResource('cache', function (Registry $register) { return new Cache(new Sharding($adapters)); }, ['register']); +Server::setResource('redis', function () { + $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); + $port = System::getEnv('_APP_REDIS_PORT', 6379); + $pass = System::getEnv('_APP_REDIS_PASS', ''); + + $redis = new \Redis(); + @$redis->pconnect($host, (int)$port); + if ($pass) { + $redis->auth($pass); + } + $redis->setOption(\Redis::OPT_READ_TIMEOUT, -1); + + return $redis; +}); + +Server::setResource('timelimit', function (\Redis $redis) { + return function (string $key, int $limit, int $time) use ($redis) { + return new TimeLimitRedis($key, $limit, $time, $redis); + }; +}, ['redis']); + Server::setResource('log', fn () => new Log()); -Server::setResource('queueForUsage', function (Connection $queue) { - return new Usage($queue); -}, ['queue']); - -Server::setResource('queueForUsageDump', function (Connection $queue) { - return new UsageDump($queue); -}, ['queue']); - -Server::setResource('queue', function (Group $pools) { - return $pools->get('queue')->pop()->getResource(); +Server::setResource('publisher', function (Group $pools) { + return $pools->get('publisher')->pop()->getResource(); }, ['pools']); -Server::setResource('queueForDatabase', function (Connection $queue) { - return new EventDatabase($queue); -}, ['queue']); +Server::setResource('consumer', function (Group $pools) { + return $pools->get('consumer')->pop()->getResource(); +}, ['pools']); -Server::setResource('queueForMessaging', function (Connection $queue) { - return new Messaging($queue); -}, ['queue']); +Server::setResource('queueForStatsUsage', function (Publisher $publisher) { + return new StatsUsage($publisher); +}, ['publisher']); -Server::setResource('queueForMails', function (Connection $queue) { - return new Mail($queue); -}, ['queue']); +Server::setResource('queueForStatsUsageDump', function (Publisher $publisher) { + return new StatsUsageDump($publisher); +}, ['publisher']); -Server::setResource('queueForBuilds', function (Connection $queue) { - return new Build($queue); -}, ['queue']); +Server::setResource('queueForDatabase', function (Publisher $publisher) { + return new EventDatabase($publisher); +}, ['publisher']); -Server::setResource('queueForDeletes', function (Connection $queue) { - return new Delete($queue); -}, ['queue']); +Server::setResource('queueForMessaging', function (Publisher $publisher) { + return new Messaging($publisher); +}, ['publisher']); -Server::setResource('queueForEvents', function (Connection $queue) { - return new Event($queue); -}, ['queue']); +Server::setResource('queueForMails', function (Publisher $publisher) { + return new Mail($publisher); +}, ['publisher']); -Server::setResource('queueForAudits', function (Connection $queue) { - return new Audit($queue); -}, ['queue']); +Server::setResource('queueForBuilds', function (Publisher $publisher) { + return new Build($publisher); +}, ['publisher']); -Server::setResource('queueForFunctions', function (Connection $queue) { - return new Func($queue); -}, ['queue']); +Server::setResource('queueForDeletes', function (Publisher $publisher) { + return new Delete($publisher); +}, ['publisher']); -Server::setResource('queueForCertificates', function (Connection $queue) { - return new Certificate($queue); -}, ['queue']); +Server::setResource('queueForEvents', function (Publisher $publisher) { + return new Event($publisher); +}, ['publisher']); -Server::setResource('queueForMigrations', function (Connection $queue) { - return new Migration($queue); -}, ['queue']); +Server::setResource('queueForAudits', function (Publisher $publisher) { + return new Audit($publisher); +}, ['publisher']); + +Server::setResource('queueForWebhooks', function (Publisher $publisher) { + return new Webhook($publisher); +}, ['publisher']); + +Server::setResource('queueForFunctions', function (Publisher $publisher) { + return new Func($publisher); +}, ['publisher']); + +Server::setResource('queueForRealtime', function () { + return new Realtime(); +}, []); + +Server::setResource('queueForCertificates', function (Publisher $publisher) { + return new Certificate($publisher); +}, ['publisher']); + +Server::setResource('queueForMigrations', function (Publisher $publisher) { + return new Migration($publisher); +}, ['publisher']); Server::setResource('logger', function (Registry $register) { return $register->get('logger'); @@ -256,6 +339,14 @@ Server::setResource('pools', function (Registry $register) { return $register->get('pools'); }, ['register']); +Server::setResource('deviceForSites', function (Document $project) { + return getDevice(APP_STORAGE_SITES . '/app-' . $project->getId()); +}, ['project']); + +Server::setResource('deviceForImports', function (Document $project) { + return getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId()); +}, ['project']); + Server::setResource('deviceForFunctions', function (Document $project) { return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId()); }, ['project']); @@ -277,6 +368,61 @@ Server::setResource( fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false ); +Server::setResource('certificates', function () { + $email = System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS')); + if (empty($email)) { + throw new Exception('You must set a valid security email address (_APP_EMAIL_CERTIFICATES) to issue a LetsEncrypt SSL certificate.'); + } + + return new LetsEncrypt($email); +}); + +Server::setResource('logError', function (Registry $register, Document $project) { + return function (Throwable $error, string $namespace, string $action, ?array $extras = null) use ($register, $project) { + $logger = $register->get('logger'); + + if ($logger) { + $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); + + $log = new Log(); + $log->setNamespace($namespace); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); + $log->setVersion($version); + $log->setType(Log::TYPE_ERROR); + $log->setMessage($error->getMessage()); + + $log->addTag('code', $error->getCode()); + $log->addTag('verboseType', get_class($error)); + $log->addTag('projectId', $project->getId() ?? ''); + + $log->addExtra('file', $error->getFile()); + $log->addExtra('line', $error->getLine()); + $log->addExtra('trace', $error->getTraceAsString()); + + + foreach (($extras ?? []) as $key => $value) { + $log->addExtra($key, $value); + } + + $log->setAction($action); + + $isProduction = System::getEnv('_APP_ENV', 'development') === 'production'; + $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); + + try { + $responseCode = $logger->addLog($log); + Console::info('Error log pushed with status code: ' . $responseCode); + } catch (Throwable $th) { + Console::error('Error pushing log: ' . $th->getMessage()); + } + } + + Console::warning("Failed: {$error->getMessage()}"); + Console::warning($error->getTraceAsString()); + }; +}, ['register', 'project']); + +Server::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST'))); $pools = $register->get('pools'); $platform = new Appwrite(); @@ -305,7 +451,7 @@ try { */ $platform->init(Service::TYPE_WORKER, [ 'workersNum' => System::getEnv('_APP_WORKERS_NUM', 1), - 'connection' => $pools->get('queue')->pop()->getResource(), + 'connection' => $pools->get('consumer')->pop()->getResource(), 'workerName' => strtolower($workerName) ?? null, 'queueName' => $queueName ]); @@ -335,7 +481,7 @@ $worker if ($logger) { $log->setNamespace("appwrite-worker"); - $log->setServer(\gethostname()); + $log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname())); $log->setVersion($version); $log->setType(Log::TYPE_ERROR); $log->setMessage($error->getMessage()); diff --git a/bin/screenshot b/bin/screenshot new file mode 100755 index 0000000000..4d8ceb998f --- /dev/null +++ b/bin/screenshot @@ -0,0 +1,3 @@ +#!/bin/sh + +php /usr/src/code/app/cli.php screenshot $@ \ No newline at end of file diff --git a/bin/stats-resources b/bin/stats-resources new file mode 100644 index 0000000000..3104bab896 --- /dev/null +++ b/bin/stats-resources @@ -0,0 +1,3 @@ +#!/bin/sh + +php /usr/src/code/app/cli.php stats-resources $@ \ No newline at end of file diff --git a/bin/worker-stats-resources b/bin/worker-stats-resources new file mode 100644 index 0000000000..9c5d2bebff --- /dev/null +++ b/bin/worker-stats-resources @@ -0,0 +1,3 @@ +#!/bin/sh + +php /usr/src/code/app/worker.php stats-resources $@ \ No newline at end of file diff --git a/bin/worker-stats-usage b/bin/worker-stats-usage new file mode 100644 index 0000000000..2c267d805e --- /dev/null +++ b/bin/worker-stats-usage @@ -0,0 +1,3 @@ +#!/bin/sh + +php /usr/src/code/app/worker.php stats-usage $@ \ No newline at end of file diff --git a/bin/worker-stats-usage-dump b/bin/worker-stats-usage-dump new file mode 100644 index 0000000000..98e3c2cac7 --- /dev/null +++ b/bin/worker-stats-usage-dump @@ -0,0 +1,3 @@ +#!/bin/sh + +php /usr/src/code/app/worker.php stats-usage-dump $@ \ No newline at end of file diff --git a/bin/worker-usage b/bin/worker-usage deleted file mode 100644 index e39ce8477c..0000000000 --- a/bin/worker-usage +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -php /usr/src/code/app/worker.php usage $@ \ No newline at end of file diff --git a/bin/worker-usage-dump b/bin/worker-usage-dump deleted file mode 100644 index 43ca87fcb3..0000000000 --- a/bin/worker-usage-dump +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -php /usr/src/code/app/worker.php usage-dump $@ \ No newline at end of file diff --git a/composer.json b/composer.json index a04ca51d43..3b5812cffb 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ "test": "vendor/bin/phpunit", "lint": "vendor/bin/pint --test", "format": "vendor/bin/pint", - "bench": "vendor/bin/phpbench run --report=benchmark" + "bench": "vendor/bin/phpbench run --report=benchmark", + "check": "./vendor/bin/phpstan analyse -c phpstan.neon" }, "autoload": { "psr-4": { @@ -43,35 +44,37 @@ "ext-openssl": "*", "ext-zlib": "*", "ext-sockets": "*", - "appwrite/php-runtimes": "0.16.*", + "appwrite/php-runtimes": "0.19.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.43.0", + "utopia-php/abuse": "0.52.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "0.43.0", - "utopia-php/cache": "0.11.*", + "utopia-php/audit": "0.55.*", + "utopia-php/cache": "0.12.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.16", + "utopia-php/detector": "0.1.*", + "utopia-php/database": "0.64.*", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", - "utopia-php/fetch": "0.2.*", - "utopia-php/image": "0.7.*", + "utopia-php/fetch": "0.4.*", + "utopia-php/image": "0.8.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", - "utopia-php/messaging": "0.12.*", - "utopia-php/migration": "0.6.*", + "utopia-php/messaging": "0.16.*", + "utopia-php/migration": "0.9.1", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", - "utopia-php/pools": "0.5.*", + "utopia-php/pools": "0.8.*", "utopia-php/preloader": "0.2.*", - "utopia-php/queue": "0.7.*", + "utopia-php/queue": "0.9.*", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", "utopia-php/swoole": "0.8.*", "utopia-php/system": "0.9.*", - "utopia-php/vcs": "0.8.*", - "utopia-php/websocket": "0.1.*", + "utopia-php/telemetry": "0.1.*", + "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", @@ -83,12 +86,13 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "0.39.*", - "phpunit/phpunit": "9.5.20", + "appwrite/sdk-generator": "0.40.*", + "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", - "textalk/websocket": "1.5.7", - "laravel/pint": "^1.14", - "phpbench/phpbench": "^1.2" + "phpstan/phpstan": "1.8.*", + "textalk/websocket": "1.5.*", + "laravel/pint": "1.*", + "phpbench/phpbench": "1.*" }, "provide": { "ext-phpiredis": "*" @@ -96,6 +100,10 @@ "config": { "platform": { "php": "8.3" + }, + "allow-plugins": { + "php-http/discovery": true, + "tbachert/spi": true } } } diff --git a/composer.lock b/composer.lock index 691a7e740e..fea7bf6d51 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": "b358198535c1867eabed7c0f99135a57", + "content-hash": "e7875026636ccec909f9aa4d79091d5b", "packages": [ { "name": "adhocore/jwt", @@ -157,16 +157,16 @@ }, { "name": "appwrite/php-runtimes", - "version": "0.16.4", + "version": "0.19.0", "source": { "type": "git", "url": "https://github.com/appwrite/runtimes.git", - "reference": "7e4741337b9373f77210396e68eca539018cabd1" + "reference": "8d21483efc19b9d977e323188989ee67a188464b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/runtimes/zipball/7e4741337b9373f77210396e68eca539018cabd1", - "reference": "7e4741337b9373f77210396e68eca539018cabd1", + "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.4" + "source": "https://github.com/appwrite/runtimes/tree/0.19.0" }, - "time": "2024-10-26T10:39:59+00:00" + "time": "2025-03-25T22:37:51+00:00" }, { "name": "beberlei/assert", @@ -277,6 +277,66 @@ }, "time": "2024-07-15T13:18:35+00:00" }, + { + "name": "brick/math", + "version": "0.12.3", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", + "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "6.8.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.12.3" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2025-02-28T13:11:00+00:00" + }, { "name": "chillerlan/php-qrcode", "version": "4.3.4", @@ -422,6 +482,87 @@ ], "time": "2024-07-17T01:04:28+00:00" }, + { + "name": "composer/semver", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-09-19T14:15:21+00:00" + }, { "name": "dragonmantank/cron-expression", "version": "v3.3.2", @@ -567,63 +708,48 @@ "time": "2024-05-03T06:31:11+00:00" }, { - "name": "jean85/pretty-package-versions", - "version": "2.0.6", + "name": "google/protobuf", + "version": "v4.30.2", "source": { "type": "git", - "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" + "url": "https://github.com/protocolbuffers/protobuf-php.git", + "reference": "a4c4d8565b40b9f76debc9dfeb221412eacb8ced" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/a4c4d8565b40b9f76debc9dfeb221412eacb8ced", + "reference": "a4c4d8565b40b9f76debc9dfeb221412eacb8ced", "shasum": "" }, "require": { - "composer-runtime-api": "^2.0.0", - "php": "^7.1|^8.0" + "php": ">=7.0.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.2", - "jean85/composer-provided-replaced-stub-package": "^1.0", - "phpstan/phpstan": "^1.4", - "phpunit/phpunit": "^7.5|^8.5|^9.4", - "vimeo/psalm": "^4.3" + "phpunit/phpunit": ">=5.0.0" + }, + "suggest": { + "ext-bcmath": "Need to support JSON deserialization" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, "autoload": { "psr-4": { - "Jean85\\": "src/" + "Google\\Protobuf\\": "src/Google/Protobuf", + "GPBMetadata\\Google\\Protobuf\\": "src/GPBMetadata/Google/Protobuf" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], - "authors": [ - { - "name": "Alessandro Lai", - "email": "alessandro.lai85@gmail.com" - } - ], - "description": "A library to get pretty versions strings of installed dependencies", + "description": "proto library for PHP", + "homepage": "https://developers.google.com/protocol-buffers/", "keywords": [ - "composer", - "package", - "release", - "versions" + "proto" ], "support": { - "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.30.2" }, - "time": "2024-03-08T09:58:59+00:00" + "time": "2025-03-26T18:01:50+00:00" }, { "name": "league/csv", @@ -783,75 +909,6 @@ }, "time": "2023-10-02T10:01:54+00:00" }, - { - "name": "mongodb/mongodb", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/mongodb/mongo-php-library.git", - "reference": "b0bbd657f84219212487d01a8ffe93a789e1e488" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/b0bbd657f84219212487d01a8ffe93a789e1e488", - "reference": "b0bbd657f84219212487d01a8ffe93a789e1e488", - "shasum": "" - }, - "require": { - "ext-hash": "*", - "ext-json": "*", - "ext-mongodb": "^1.11.0", - "jean85/pretty-package-versions": "^1.2 || ^2.0.1", - "php": "^7.1 || ^8.0", - "symfony/polyfill-php80": "^1.19" - }, - "require-dev": { - "doctrine/coding-standard": "^9.0", - "squizlabs/php_codesniffer": "^3.6", - "symfony/phpunit-bridge": "^5.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "MongoDB\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Andreas Braun", - "email": "andreas.braun@mongodb.com" - }, - { - "name": "Jeremy Mikola", - "email": "jmikola@gmail.com" - } - ], - "description": "MongoDB driver library", - "homepage": "https://jira.mongodb.org/browse/PHPLIB", - "keywords": [ - "database", - "driver", - "mongodb", - "persistence" - ], - "support": { - "issues": "https://github.com/mongodb/mongo-php-library/issues", - "source": "https://github.com/mongodb/mongo-php-library/tree/1.10.0" - }, - "time": "2021-10-20T22:22:37+00:00" - }, { "name": "mustangostang/spyc", "version": "0.6.3", @@ -906,6 +963,553 @@ }, "time": "2019-09-10T13:16:29+00:00" }, + { + "name": "nyholm/psr7", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7.git", + "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3", + "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0", + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "^0.9", + "php-http/message-factory": "^1.0", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", + "symfony/error-handler": "^4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Nyholm\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "https://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7/issues", + "source": "https://github.com/Nyholm/psr7/tree/1.8.2" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2024-09-09T07:06:30+00:00" + }, + { + "name": "nyholm/psr7-server", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7-server.git", + "reference": "4335801d851f554ca43fa6e7d2602141538854dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7-server/zipball/4335801d851f554ca43fa6e7d2602141538854dc", + "reference": "4335801d851f554ca43fa6e7d2602141538854dc", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "require-dev": { + "nyholm/nsa": "^1.1", + "nyholm/psr7": "^1.3", + "phpunit/phpunit": "^7.0 || ^8.5 || ^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Nyholm\\Psr7Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "Helper classes to handle PSR-7 server requests", + "homepage": "http://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7-server/issues", + "source": "https://github.com/Nyholm/psr7-server/tree/1.1.0" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2023-11-08T09:30:43+00:00" + }, + { + "name": "open-telemetry/api", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/api.git", + "reference": "199d7ddda88f5f5619fa73463f1a5a7149ccd1f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/199d7ddda88f5f5619fa73463f1a5a7149ccd1f1", + "reference": "199d7ddda88f5f5619fa73463f1a5a7149ccd1f1", + "shasum": "" + }, + "require": { + "open-telemetry/context": "^1.0", + "php": "^8.1", + "psr/log": "^1.1|^2.0|^3.0", + "symfony/polyfill-php82": "^1.26" + }, + "conflict": { + "open-telemetry/sdk": "<=1.0.8" + }, + "type": "library", + "extra": { + "spi": { + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" + ] + }, + "branch-alias": { + "dev-main": "1.1.x-dev" + } + }, + "autoload": { + "files": [ + "Trace/functions.php" + ], + "psr-4": { + "OpenTelemetry\\API\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "API for OpenTelemetry PHP.", + "keywords": [ + "Metrics", + "api", + "apm", + "logging", + "opentelemetry", + "otel", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "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" + }, + { + "name": "open-telemetry/context", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/context.git", + "reference": "0cba875ea1953435f78aec7f1d75afa87bdbf7f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/context/zipball/0cba875ea1953435f78aec7f1d75afa87bdbf7f3", + "reference": "0cba875ea1953435f78aec7f1d75afa87bdbf7f3", + "shasum": "" + }, + "require": { + "php": "^8.1", + "symfony/polyfill-php82": "^1.26" + }, + "suggest": { + "ext-ffi": "To allow context switching in Fibers" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0.x-dev" + } + }, + "autoload": { + "files": [ + "fiber/initialize_fiber_handler.php" + ], + "psr-4": { + "OpenTelemetry\\Context\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "Context implementation for OpenTelemetry PHP.", + "keywords": [ + "Context", + "opentelemetry", + "otel" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php" + }, + "time": "2024-08-21T00:29:20+00:00" + }, + { + "name": "open-telemetry/exporter-otlp", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/exporter-otlp.git", + "reference": "b7580440b7481a98da97aceabeb46e1b276c8747" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/b7580440b7481a98da97aceabeb46e1b276c8747", + "reference": "b7580440b7481a98da97aceabeb46e1b276c8747", + "shasum": "" + }, + "require": { + "open-telemetry/api": "^1.0", + "open-telemetry/gen-otlp-protobuf": "^1.1", + "open-telemetry/sdk": "^1.0", + "php": "^8.1", + "php-http/discovery": "^1.14" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.0.x-dev" + } + }, + "autoload": { + "files": [ + "_register.php" + ], + "psr-4": { + "OpenTelemetry\\Contrib\\Otlp\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "OTLP exporter for OpenTelemetry.", + "keywords": [ + "Metrics", + "exporter", + "gRPC", + "http", + "opentelemetry", + "otel", + "otlp", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "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" + }, + { + "name": "open-telemetry/gen-otlp-protobuf", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/gen-otlp-protobuf.git", + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/gen-otlp-protobuf/zipball/585bafddd4ae6565de154610b10a787a455c9ba0", + "reference": "585bafddd4ae6565de154610b10a787a455c9ba0", + "shasum": "" + }, + "require": { + "google/protobuf": "^3.22 || ^4.0", + "php": "^8.0" + }, + "suggest": { + "ext-protobuf": "For better performance, when dealing with the protobuf format" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opentelemetry\\Proto\\": "Opentelemetry/Proto/", + "GPBMetadata\\Opentelemetry\\": "GPBMetadata/Opentelemetry/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "PHP protobuf files for communication with OpenTelemetry OTLP collectors/servers.", + "keywords": [ + "Metrics", + "apm", + "gRPC", + "logging", + "opentelemetry", + "otel", + "otlp", + "protobuf", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php" + }, + "time": "2025-01-15T23:07:07+00:00" + }, + { + "name": "open-telemetry/sdk", + "version": "1.2.4", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/sdk.git", + "reference": "47fcb66ae5328c5a799195247b1dce551d85873e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/47fcb66ae5328c5a799195247b1dce551d85873e", + "reference": "47fcb66ae5328c5a799195247b1dce551d85873e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "nyholm/psr7-server": "^1.1", + "open-telemetry/api": "~1.0 || ~1.1", + "open-telemetry/context": "^1.0", + "open-telemetry/sem-conv": "^1.0", + "php": "^8.1", + "php-http/discovery": "^1.14", + "psr/http-client": "^1.0", + "psr/http-client-implementation": "^1.0", + "psr/http-factory-implementation": "^1.0", + "psr/http-message": "^1.0.1|^2.0", + "psr/log": "^1.1|^2.0|^3.0", + "ramsey/uuid": "^3.0 || ^4.0", + "symfony/polyfill-mbstring": "^1.23", + "symfony/polyfill-php82": "^1.26", + "tbachert/spi": "^1.0.1" + }, + "suggest": { + "ext-gmp": "To support unlimited number of synchronous metric readers", + "ext-mbstring": "To increase performance of string operations", + "open-telemetry/sdk-configuration": "File-based OpenTelemetry SDK configuration" + }, + "type": "library", + "extra": { + "spi": { + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ + "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" + ] + }, + "branch-alias": { + "dev-main": "1.0.x-dev" + } + }, + "autoload": { + "files": [ + "Common/Util/functions.php", + "Logs/Exporter/_register.php", + "Metrics/MetricExporter/_register.php", + "Propagation/_register.php", + "Trace/SpanExporter/_register.php", + "Common/Dev/Compatibility/_load.php", + "_autoload.php" + ], + "psr-4": { + "OpenTelemetry\\SDK\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "SDK for OpenTelemetry PHP.", + "keywords": [ + "Metrics", + "apm", + "logging", + "opentelemetry", + "otel", + "sdk", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php" + }, + "time": "2025-04-15T07:02:07+00:00" + }, + { + "name": "open-telemetry/sem-conv", + "version": "1.30.0", + "source": { + "type": "git", + "url": "https://github.com/opentelemetry-php/sem-conv.git", + "reference": "4178c9f390da8e4dbca9b181a9d1efd50cf7ee0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opentelemetry-php/sem-conv/zipball/4178c9f390da8e4dbca9b181a9d1efd50cf7ee0a", + "reference": "4178c9f390da8e4dbca9b181a9d1efd50cf7ee0a", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "OpenTelemetry\\SemConv\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "opentelemetry-php contributors", + "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" + } + ], + "description": "Semantic conventions for OpenTelemetry PHP.", + "keywords": [ + "Metrics", + "apm", + "logging", + "opentelemetry", + "otel", + "semantic conventions", + "semconv", + "tracing" + ], + "support": { + "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", + "docs": "https://opentelemetry.io/docs/php", + "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", + "source": "https://github.com/open-telemetry/opentelemetry-php" + }, + "time": "2025-02-06T00:21:48+00:00" + }, { "name": "paragonie/constant_time_encoding", "version": "v2.7.0", @@ -973,6 +1577,216 @@ }, "time": "2024-05-08T12:18:48+00:00" }, + { + "name": "paragonie/random_compat", + "version": "v9.99.100", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" + }, + { + "name": "php-amqplib/php-amqplib", + "version": "v3.7.3", + "source": { + "type": "git", + "url": "https://github.com/php-amqplib/php-amqplib.git", + "reference": "9f50fe69a9f1a19e2cb25596a354d705de36fe59" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/9f50fe69a9f1a19e2cb25596a354d705de36fe59", + "reference": "9f50fe69a9f1a19e2cb25596a354d705de36fe59", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-sockets": "*", + "php": "^7.2||^8.0", + "phpseclib/phpseclib": "^2.0|^3.0" + }, + "conflict": { + "php": "7.4.0 - 7.4.1" + }, + "replace": { + "videlalvaro/php-amqplib": "self.version" + }, + "require-dev": { + "ext-curl": "*", + "nategood/httpful": "^0.2.20", + "phpunit/phpunit": "^7.5|^9.5", + "squizlabs/php_codesniffer": "^3.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpAmqpLib\\": "PhpAmqpLib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Alvaro Videla", + "role": "Original Maintainer" + }, + { + "name": "Raúl Araya", + "email": "nubeiro@gmail.com", + "role": "Maintainer" + }, + { + "name": "Luke Bakken", + "email": "luke@bakken.io", + "role": "Maintainer" + }, + { + "name": "Ramūnas Dronga", + "email": "github@ramuno.lt", + "role": "Maintainer" + } + ], + "description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.", + "homepage": "https://github.com/php-amqplib/php-amqplib/", + "keywords": [ + "message", + "queue", + "rabbitmq" + ], + "support": { + "issues": "https://github.com/php-amqplib/php-amqplib/issues", + "source": "https://github.com/php-amqplib/php-amqplib/tree/v3.7.3" + }, + "time": "2025-02-18T20:11:13+00:00" + }, + { + "name": "php-http/discovery", + "version": "1.20.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/82fe4c73ef3363caed49ff8dd1539ba06044910d", + "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0", + "zendframework/zend-diactoros": "*" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "*", + "psr/http-factory-implementation": "*", + "psr/http-message-implementation": "*" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", + "sebastian/comparator": "^3.0.5 || ^4.0.8", + "symfony/phpunit-bridge": "^6.4.4 || ^7.0.1" + }, + "type": "composer-plugin", + "extra": { + "class": "Http\\Discovery\\Composer\\Plugin", + "plugin-optional": true + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + }, + "exclude-from-classmap": [ + "src/Composer/Plugin.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr17", + "psr7" + ], + "support": { + "issues": "https://github.com/php-http/discovery/issues", + "source": "https://github.com/php-http/discovery/tree/1.20.0" + }, + "time": "2024-10-02T11:20:13+00:00" + }, { "name": "phpmailer/phpmailer", "version": "v6.9.1", @@ -1054,6 +1868,547 @@ ], "time": "2023-11-25T22:23:28+00:00" }, + { + "name": "phpseclib/phpseclib", + "version": "3.0.43", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "709ec107af3cb2f385b9617be72af8cf62441d02" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02", + "reference": "709ec107af3cb2f385b9617be72af8cf62441d02", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^1|^2|^3", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": ">=5.6.1" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "ext-dom": "Install the DOM extension to load XML formatted public keys.", + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib3\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.43" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2024-12-14T21:12:59+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.1.1" + }, + "time": "2025-03-22T05:38:12+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.7.6", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "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", + "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" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.7.6" + }, + "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" + }, { "name": "spomky-labs/otphp", "version": "v10.0.3", @@ -1088,9 +2443,9 @@ "type": "library", "extra": { "branch-alias": { - "v10.0": "10.0.x-dev", + "v8.3": "8.3.x-dev", "v9.0": "9.0.x-dev", - "v8.3": "8.3.x-dev" + "v10.0": "10.0.x-dev" } }, "autoload": { @@ -1129,6 +2484,246 @@ }, "time": "2022-03-17T08:00:35+00:00" }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "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" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/http-client", + "version": "v7.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", + "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "~3.4.4|^3.5.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "amphp/amp": "<2.5", + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/http-client": "^4.2.1|^5.0", + "amphp/http-tunnel": "^1.0|^2.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/amphp-http-client-meta": "^1.0|^2.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v7.2.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-02-13T10:27:23+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", + "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-07T08:49:48+00:00" + }, { "name": "symfony/polyfill-mbstring", "version": "v1.31.0", @@ -1155,8 +2750,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1210,17 +2805,17 @@ "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php80", + "name": "symfony/polyfill-php82", "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "url": "https://github.com/symfony/polyfill-php82.git", + "reference": "5d2ed36f7734637dacc025f179698031951b1692" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/5d2ed36f7734637dacc025f179698031951b1692", + "reference": "5d2ed36f7734637dacc025f179698031951b1692", "shasum": "" }, "require": { @@ -1229,8 +2824,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -1238,7 +2833,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Php82\\": "" }, "classmap": [ "Resources/stubs" @@ -1249,10 +2844,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -1262,7 +2853,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -1271,7 +2862,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php82/tree/v1.31.0" }, "funding": [ { @@ -1289,6 +2880,141 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/service-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "tbachert/spi", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/Nevay/spi.git", + "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nevay/spi/zipball/506a79c98e1a51522e76ee921ccb6c62d52faf3a", + "reference": "506a79c98e1a51522e76ee921ccb6c62d52faf3a", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "composer/semver": "^1.0 || ^2.0 || ^3.0", + "php": "^8.1" + }, + "require-dev": { + "composer/composer": "^2.0", + "infection/infection": "^0.27.9", + "phpunit/phpunit": "^10.5", + "psalm/phar": "^5.18" + }, + "type": "composer-plugin", + "extra": { + "class": "Nevay\\SPI\\Composer\\Plugin", + "branch-alias": { + "dev-main": "0.2.x-dev" + }, + "plugin-optional": true + }, + "autoload": { + "psr-4": { + "Nevay\\SPI\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "Service provider loading facility", + "keywords": [ + "service provider" + ], + "support": { + "issues": "https://github.com/Nevay/spi/issues", + "source": "https://github.com/Nevay/spi/tree/v1.0.3" + }, + "time": "2025-04-02T19:38:14+00:00" + }, { "name": "thecodingmachine/safe", "version": "v2.5.0", @@ -1430,16 +3156,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.43.0", + "version": "0.52.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "6346a3b4c5177a43160035a7289e30fdfb0790d6" + "reference": "a0d6421e7e5baa3ac02755496dca9fdeaa814b93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/6346a3b4c5177a43160035a7289e30fdfb0790d6", - "reference": "6346a3b4c5177a43160035a7289e30fdfb0790d6", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/a0d6421e7e5baa3ac02755496dca9fdeaa814b93", + "reference": "a0d6421e7e5baa3ac02755496dca9fdeaa814b93", "shasum": "" }, "require": { @@ -1447,13 +3173,13 @@ "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "0.53.*" + "utopia-php/database": "0.*.*" }, "require-dev": { - "laravel/pint": "1.5.*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9.4" + "laravel/pint": "1.*", + "phpbench/phpbench": "1.*", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "9.*" }, "type": "library", "autoload": { @@ -1475,9 +3201,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.43.0" + "source": "https://github.com/utopia-php/abuse/tree/0.52.0" }, - "time": "2024-08-30T05:17:23+00:00" + "time": "2025-03-06T03:48:29+00:00" }, { "name": "utopia-php/analytics", @@ -1527,26 +3253,26 @@ }, { "name": "utopia-php/audit", - "version": "0.43.0", + "version": "0.55.0", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "cef22b5dc6a6d28fcd522f41c7bf7ded4a4dfd3e" + "reference": "9f8cfe5fa5d5011b8dbf93b710236dfa91dc5518" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/cef22b5dc6a6d28fcd522f41c7bf7ded4a4dfd3e", - "reference": "cef22b5dc6a6d28fcd522f41c7bf7ded4a4dfd3e", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/9f8cfe5fa5d5011b8dbf93b710236dfa91dc5518", + "reference": "9f8cfe5fa5d5011b8dbf93b710236dfa91dc5518", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.53.*" + "utopia-php/database": "0.*.*" }, "require-dev": { - "laravel/pint": "1.5.*", - "phpstan/phpstan": "^1.8", - "phpunit/phpunit": "^9.3" + "laravel/pint": "1.*", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "9.*" }, "type": "library", "autoload": { @@ -1568,29 +3294,30 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.43.0" + "source": "https://github.com/utopia-php/audit/tree/0.55.0" }, - "time": "2024-08-30T05:17:36+00:00" + "time": "2025-03-06T03:47:47+00:00" }, { "name": "utopia-php/cache", - "version": "0.11.0", + "version": "0.12.0", "source": { "type": "git", "url": "https://github.com/utopia-php/cache.git", - "reference": "8ebcab5aac7606331cef69b0081f6c9eff2e58bc" + "reference": "646038f1d470b759c129348be8fc14da3c00bbd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/cache/zipball/8ebcab5aac7606331cef69b0081f6c9eff2e58bc", - "reference": "8ebcab5aac7606331cef69b0081f6c9eff2e58bc", + "url": "https://api.github.com/repos/utopia-php/cache/zipball/646038f1d470b759c129348be8fc14da3c00bbd9", + "reference": "646038f1d470b759c129348be8fc14da3c00bbd9", "shasum": "" }, "require": { "ext-json": "*", "ext-memcached": "*", "ext-redis": "*", - "php": ">=8.0" + "php": ">=8.0", + "utopia-php/telemetry": "0.1.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -1618,22 +3345,22 @@ ], "support": { "issues": "https://github.com/utopia-php/cache/issues", - "source": "https://github.com/utopia-php/cache/tree/0.11.0" + "source": "https://github.com/utopia-php/cache/tree/0.12.0" }, - "time": "2024-11-05T16:53:58+00:00" + "time": "2025-02-25T09:09:21+00:00" }, { "name": "utopia-php/cli", - "version": "0.15.1", + "version": "0.15.2", "source": { "type": "git", "url": "https://github.com/utopia-php/cli.git", - "reference": "d69bbe51a6a94dc4e5bcdd542b5938038b985a65" + "reference": "da00ff6b8b29a826a1794002ae43442cdf3a0f5f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/cli/zipball/d69bbe51a6a94dc4e5bcdd542b5938038b985a65", - "reference": "d69bbe51a6a94dc4e5bcdd542b5938038b985a65", + "url": "https://api.github.com/repos/utopia-php/cli/zipball/da00ff6b8b29a826a1794002ae43442cdf3a0f5f", + "reference": "da00ff6b8b29a826a1794002ae43442cdf3a0f5f", "shasum": "" }, "require": { @@ -1667,22 +3394,22 @@ ], "support": { "issues": "https://github.com/utopia-php/cli/issues", - "source": "https://github.com/utopia-php/cli/tree/0.15.1" + "source": "https://github.com/utopia-php/cli/tree/0.15.2" }, - "time": "2024-10-04T13:55:36+00:00" + "time": "2025-04-15T10:08:48+00:00" }, { "name": "utopia-php/compression", - "version": "0.1.2", + "version": "0.1.3", "source": { "type": "git", "url": "https://github.com/utopia-php/compression.git", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98" + "reference": "66f093557ba66d98245e562036182016c7dcfe8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/compression/zipball/6062f70596415f8d5de40a589367b0eb2a435f98", - "reference": "6062f70596415f8d5de40a589367b0eb2a435f98", + "url": "https://api.github.com/repos/utopia-php/compression/zipball/66f093557ba66d98245e562036182016c7dcfe8a", + "reference": "66f093557ba66d98245e562036182016c7dcfe8a", "shasum": "" }, "require": { @@ -1713,9 +3440,9 @@ ], "support": { "issues": "https://github.com/utopia-php/compression/issues", - "source": "https://github.com/utopia-php/compression/tree/0.1.2" + "source": "https://github.com/utopia-php/compression/tree/0.1.3" }, - "time": "2024-11-08T14:59:54+00:00" + "time": "2025-01-15T15:15:51+00:00" }, { "name": "utopia-php/config", @@ -1770,25 +3497,25 @@ }, { "name": "utopia-php/database", - "version": "0.53.16", + "version": "0.64.2", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "6661edffeef05b59e16d102b989a72f7f78cf7de" + "reference": "dc9c4a68c93e8bea2dfaa76d1ba308be539998bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/6661edffeef05b59e16d102b989a72f7f78cf7de", - "reference": "6661edffeef05b59e16d102b989a72f7f78cf7de", + "url": "https://api.github.com/repos/utopia-php/database/zipball/dc9c4a68c93e8bea2dfaa76d1ba308be539998bd", + "reference": "dc9c4a68c93e8bea2dfaa76d1ba308be539998bd", "shasum": "" }, "require": { "ext-mbstring": "*", "ext-pdo": "*", - "php": ">=8.3", - "utopia-php/cache": "0.11.*", + "php": ">=8.1", + "utopia-php/cache": "0.12.*", "utopia-php/framework": "0.33.*", - "utopia-php/mongo": "0.3.*" + "utopia-php/pools": "0.8.*" }, "require-dev": { "fakerphp/faker": "1.23.*", @@ -1820,9 +3547,54 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.53.16" + "source": "https://github.com/utopia-php/database/tree/0.64.2" }, - "time": "2024-11-06T03:07:16+00:00" + "time": "2025-04-09T07:53:05+00:00" + }, + { + "name": "utopia-php/detector", + "version": "0.1.4", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/detector.git", + "reference": "895a4147463965b5f9cbc083b764b6476f547879" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/detector/zipball/895a4147463965b5f9cbc083b764b6476f547879", + "reference": "895a4147463965b5f9cbc083b764b6476f547879", + "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.4" + }, + "time": "2025-04-09T11:50:45+00:00" }, { "name": "utopia-php/domains", @@ -1933,16 +3705,16 @@ }, { "name": "utopia-php/fetch", - "version": "0.2.1", + "version": "0.4.1", "source": { "type": "git", "url": "https://github.com/utopia-php/fetch.git", - "reference": "1423c0ee3eef944d816ca6e31706895b585aea82" + "reference": "65095dac14037db0c822fb5e209e5bd3187a0303" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/fetch/zipball/1423c0ee3eef944d816ca6e31706895b585aea82", - "reference": "1423c0ee3eef944d816ca6e31706895b585aea82", + "url": "https://api.github.com/repos/utopia-php/fetch/zipball/65095dac14037db0c822fb5e209e5bd3187a0303", + "reference": "65095dac14037db0c822fb5e209e5bd3187a0303", "shasum": "" }, "require": { @@ -1966,27 +3738,28 @@ "description": "A simple library that provides an interface for making HTTP Requests.", "support": { "issues": "https://github.com/utopia-php/fetch/issues", - "source": "https://github.com/utopia-php/fetch/tree/0.2.1" + "source": "https://github.com/utopia-php/fetch/tree/0.4.1" }, - "time": "2024-03-18T11:50:59+00:00" + "time": "2025-04-14T07:34:27+00:00" }, { "name": "utopia-php/framework", - "version": "0.33.11", + "version": "0.33.19", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "354ff0d23bfc6e82bea0fe8e89e115cff1af8466" + "reference": "64c7b7bb8a8595ffe875fa8d4b7705684dbf46c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/354ff0d23bfc6e82bea0fe8e89e115cff1af8466", - "reference": "354ff0d23bfc6e82bea0fe8e89e115cff1af8466", + "url": "https://api.github.com/repos/utopia-php/http/zipball/64c7b7bb8a8595ffe875fa8d4b7705684dbf46c0", + "reference": "64c7b7bb8a8595ffe875fa8d4b7705684dbf46c0", "shasum": "" }, "require": { - "php": ">=8.0", - "utopia-php/compression": "0.1.*" + "php": ">=8.1", + "utopia-php/compression": "0.1.*", + "utopia-php/telemetry": "0.1.*" }, "require-dev": { "laravel/pint": "^1.2", @@ -2012,31 +3785,32 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.11" + "source": "https://github.com/utopia-php/http/tree/0.33.19" }, - "time": "2024-11-08T18:47:43+00:00" + "time": "2025-03-06T11:37:49+00:00" }, { "name": "utopia-php/image", - "version": "0.7.0", + "version": "0.8.2", "source": { "type": "git", "url": "https://github.com/utopia-php/image.git", - "reference": "fcea143edbad524bf871ddbebe801d981f91f181" + "reference": "6c736965177f9a9e71311e22b80cfa88511768e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/image/zipball/fcea143edbad524bf871ddbebe801d981f91f181", - "reference": "fcea143edbad524bf871ddbebe801d981f91f181", + "url": "https://api.github.com/repos/utopia-php/image/zipball/6c736965177f9a9e71311e22b80cfa88511768e9", + "reference": "6c736965177f9a9e71311e22b80cfa88511768e9", "shasum": "" }, "require": { + "ext-gd": "*", "ext-imagick": "*", "php": ">=8.1" }, "require-dev": { "laravel/pint": "1.2.*", - "phpstan/phpstan": "1.9.x-dev", + "phpstan/phpstan": "^1.10.0", "phpunit/phpunit": "^9.3", "vimeo/psalm": "4.13.1" }, @@ -2060,9 +3834,9 @@ ], "support": { "issues": "https://github.com/utopia-php/image/issues", - "source": "https://github.com/utopia-php/image/tree/0.7.0" + "source": "https://github.com/utopia-php/image/tree/0.8.2" }, - "time": "2024-10-02T05:45:38+00:00" + "time": "2025-04-08T11:31:45+00:00" }, { "name": "utopia-php/locale", @@ -2171,16 +3945,16 @@ }, { "name": "utopia-php/messaging", - "version": "0.12.2", + "version": "0.16.0", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "f6790fba1fcee12163d51c65d2c226a7856295d9" + "reference": "5f3083697102b1821d6624938186761b1e09c54e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/f6790fba1fcee12163d51c65d2c226a7856295d9", - "reference": "f6790fba1fcee12163d51c65d2c226a7856295d9", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/5f3083697102b1821d6624938186761b1e09c54e", + "reference": "5f3083697102b1821d6624938186761b1e09c54e", "shasum": "" }, "require": { @@ -2191,9 +3965,9 @@ "phpmailer/phpmailer": "6.9.1" }, "require-dev": { - "laravel/pint": "1.13.11", - "phpstan/phpstan": "1.10.58", - "phpunit/phpunit": "10.5.10" + "laravel/pint": "1.*", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "11.*" }, "type": "library", "autoload": { @@ -2216,41 +3990,41 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.12.2" + "source": "https://github.com/utopia-php/messaging/tree/0.16.0" }, - "time": "2024-10-22T01:02:20+00:00" + "time": "2025-02-18T08:27:00+00:00" }, { "name": "utopia-php/migration", - "version": "0.6.11", + "version": "0.9.1", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "4d167914d3f7fa1fe816b2b2c6f221e70166bfd7" + "reference": "f8b54727c7b0abe416a74a2a4c9fa4350c7a59a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/4d167914d3f7fa1fe816b2b2c6f221e70166bfd7", - "reference": "4d167914d3f7fa1fe816b2b2c6f221e70166bfd7", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/f8b54727c7b0abe416a74a2a4c9fa4350c7a59a3", + "reference": "f8b54727c7b0abe416a74a2a4c9fa4350c7a59a3", "shasum": "" }, "require": { - "appwrite/appwrite": "11.1.*", + "appwrite/appwrite": "11.*", "ext-curl": "*", "ext-openssl": "*", - "php": "8.3.*", - "utopia-php/database": "0.53.*", + "php": ">=8.1", + "utopia-php/database": "0.*.*", "utopia-php/dsn": "0.2.*", "utopia-php/framework": "0.33.*", "utopia-php/storage": "0.18.*" }, "require-dev": { "ext-pdo": "*", - "laravel/pint": "1.17.*", - "phpstan/phpstan": "1.11.*", - "phpunit/phpunit": "11.2.*", + "laravel/pint": "1.*", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "11.*", "utopia-php/cli": "0.16.*", - "vlucas/phpdotenv": "5.6.*" + "vlucas/phpdotenv": "5.*" }, "type": "library", "autoload": { @@ -2272,69 +4046,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.6.11" + "source": "https://github.com/utopia-php/migration/tree/0.9.1" }, - "time": "2024-10-31T06:19:57+00:00" - }, - { - "name": "utopia-php/mongo", - "version": "0.3.1", - "source": { - "type": "git", - "url": "https://github.com/utopia-php/mongo.git", - "reference": "52326a9a43e2d27ff0c15c48ba746dacbe9a7aee" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/utopia-php/mongo/zipball/52326a9a43e2d27ff0c15c48ba746dacbe9a7aee", - "reference": "52326a9a43e2d27ff0c15c48ba746dacbe9a7aee", - "shasum": "" - }, - "require": { - "ext-mongodb": "*", - "mongodb/mongodb": "1.10.0", - "php": ">=8.0" - }, - "require-dev": { - "fakerphp/faker": "^1.14", - "laravel/pint": "1.2.*", - "phpstan/phpstan": "1.8.*", - "phpunit/phpunit": "^9.4", - "swoole/ide-helper": "4.8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Utopia\\Mongo\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Eldad Fux", - "email": "eldad@appwrite.io" - }, - { - "name": "Wess", - "email": "wess@appwrite.io" - } - ], - "description": "A simple library to manage Mongo database", - "keywords": [ - "database", - "mongo", - "php", - "upf", - "utopia" - ], - "support": { - "issues": "https://github.com/utopia-php/mongo/issues", - "source": "https://github.com/utopia-php/mongo/tree/0.3.1" - }, - "time": "2023-09-01T17:25:28+00:00" + "time": "2025-04-17T05:18:58+00:00" }, { "name": "utopia-php/orchestration", @@ -2388,16 +4102,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.1", + "version": "0.7.4", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a" + "reference": "a5b93d8177702ec458c3af9137663133c012b71b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/3433a0f1a54988f2a59c735f507745cb2c24638a", - "reference": "3433a0f1a54988f2a59c735f507745cb2c24638a", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/a5b93d8177702ec458c3af9137663133c012b71b", + "reference": "a5b93d8177702ec458c3af9137663133c012b71b", "shasum": "" }, "require": { @@ -2406,7 +4120,7 @@ "php": ">=8.0", "utopia-php/cli": "0.15.*", "utopia-php/framework": "0.33.*", - "utopia-php/queue": "0.7.*" + "utopia-php/queue": "0.9.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -2432,31 +4146,32 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.1" + "source": "https://github.com/utopia-php/platform/tree/0.7.4" }, - "time": "2024-10-22T10:27:49+00:00" + "time": "2025-03-13T13:00:12+00:00" }, { "name": "utopia-php/pools", - "version": "0.5.0", + "version": "0.8.2", "source": { "type": "git", "url": "https://github.com/utopia-php/pools.git", - "reference": "6f716a213a08db95eda1b5dddfa90983c1834817" + "reference": "05c67aba42eb68ac65489cc1e7fc5db83db2dd4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/pools/zipball/6f716a213a08db95eda1b5dddfa90983c1834817", - "reference": "6f716a213a08db95eda1b5dddfa90983c1834817", + "url": "https://api.github.com/repos/utopia-php/pools/zipball/05c67aba42eb68ac65489cc1e7fc5db83db2dd4d", + "reference": "05c67aba42eb68ac65489cc1e7fc5db83db2dd4d", "shasum": "" }, "require": { - "php": ">=8.0" + "php": ">=8.3", + "utopia-php/telemetry": "0.1.*" }, "require-dev": { - "laravel/pint": "1.2.*", - "phpstan/phpstan": "1.8.*", - "phpunit/phpunit": "^9.3" + "laravel/pint": "1.*", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "11.*" }, "type": "library", "autoload": { @@ -2483,9 +4198,9 @@ ], "support": { "issues": "https://github.com/utopia-php/pools/issues", - "source": "https://github.com/utopia-php/pools/tree/0.5.0" + "source": "https://github.com/utopia-php/pools/tree/0.8.2" }, - "time": "2024-04-19T11:11:54+00:00" + "time": "2025-04-17T02:04:54+00:00" }, { "name": "utopia-php/preloader", @@ -2542,24 +4257,28 @@ }, { "name": "utopia-php/queue", - "version": "0.7.1", + "version": "0.9.1", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "94c240d9f6383829807ce7b2d737f04b159fd3e8" + "reference": "32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/94c240d9f6383829807ce7b2d737f04b159fd3e8", - "reference": "94c240d9f6383829807ce7b2d737f04b159fd3e8", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32", + "reference": "32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32", "shasum": "" }, "require": { - "php": ">=8.0", + "php": ">=8.3", + "php-amqplib/php-amqplib": "^3.7", "utopia-php/cli": "0.15.*", - "utopia-php/framework": "0.*.*" + "utopia-php/fetch": "0.4.*", + "utopia-php/framework": "0.33.*", + "utopia-php/telemetry": "0.1.*" }, "require-dev": { + "ext-redis": "*", "laravel/pint": "^0.2.3", "phpstan/phpstan": "^1.8", "phpunit/phpunit": "^9.5.5", @@ -2597,9 +4316,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.7.1" + "source": "https://github.com/utopia-php/queue/tree/0.9.1" }, - "time": "2024-11-05T17:00:38+00:00" + "time": "2025-03-28T19:49:36+00:00" }, { "name": "utopia-php/registry", @@ -2655,22 +4374,24 @@ }, { "name": "utopia-php/storage", - "version": "0.18.6", + "version": "0.18.10", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "893ccf06e183f8ece2aed8dbf14d64d6ba036071" + "reference": "76f31158f4251abb207f7a9b16f7cb0bfdb3b39e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/893ccf06e183f8ece2aed8dbf14d64d6ba036071", - "reference": "893ccf06e183f8ece2aed8dbf14d64d6ba036071", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/76f31158f4251abb207f7a9b16f7cb0bfdb3b39e", + "reference": "76f31158f4251abb207f7a9b16f7cb0bfdb3b39e", "shasum": "" }, "require": { "ext-brotli": "*", + "ext-curl": "*", "ext-fileinfo": "*", "ext-lz4": "*", + "ext-simplexml": "*", "ext-snappy": "*", "ext-xz": "*", "ext-zlib": "*", @@ -2704,22 +4425,22 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.6" + "source": "https://github.com/utopia-php/storage/tree/0.18.10" }, - "time": "2024-11-06T09:58:50+00:00" + "time": "2025-03-03T10:47:54+00:00" }, { "name": "utopia-php/swoole", - "version": "0.8.2", + "version": "0.8.3", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4" + "reference": "1af73dd3e73987cf729c7db399054e4a70befd99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4", - "reference": "5fa9d42c608ad46a4ce42a6d2b2eae00592fccd4", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/1af73dd3e73987cf729c7db399054e4a70befd99", + "reference": "1af73dd3e73987cf729c7db399054e4a70befd99", "shasum": "" }, "require": { @@ -2755,9 +4476,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.8.2" + "source": "https://github.com/utopia-php/swoole/tree/0.8.3" }, - "time": "2024-02-01T14:54:12+00:00" + "time": "2025-03-26T10:09:05+00:00" }, { "name": "utopia-php/system", @@ -2816,24 +4537,75 @@ "time": "2024-10-09T14:44:01+00:00" }, { - "name": "utopia-php/vcs", - "version": "0.8.3", + "name": "utopia-php/telemetry", + "version": "0.1.1", "source": { "type": "git", - "url": "https://github.com/utopia-php/vcs.git", - "reference": "a032ed0611a8f4467aeaa9484f73223074457337" + "url": "https://github.com/utopia-php/telemetry.git", + "reference": "437f0021777f0e575dfb9e8a1a081b3aed75e33f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/a032ed0611a8f4467aeaa9484f73223074457337", - "reference": "a032ed0611a8f4467aeaa9484f73223074457337", + "url": "https://api.github.com/repos/utopia-php/telemetry/zipball/437f0021777f0e575dfb9e8a1a081b3aed75e33f", + "reference": "437f0021777f0e575dfb9e8a1a081b3aed75e33f", + "shasum": "" + }, + "require": { + "ext-opentelemetry": "*", + "ext-protobuf": "*", + "nyholm/psr7": "^1.8", + "open-telemetry/exporter-otlp": "^1.1", + "open-telemetry/sdk": "^1.1", + "php": ">=8.0", + "symfony/http-client": "^7.1" + }, + "require-dev": { + "laravel/pint": "^1.2", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.25" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Telemetry\\": "src/Telemetry" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "keywords": [ + "framework", + "php", + "upf" + ], + "support": { + "issues": "https://github.com/utopia-php/telemetry/issues", + "source": "https://github.com/utopia-php/telemetry/tree/0.1.1" + }, + "time": "2025-03-17T11:57:52+00:00" + }, + { + "name": "utopia-php/vcs", + "version": "0.10.1", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/vcs.git", + "reference": "6be02650cc361764900ade8c129f309df263eb74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/6be02650cc361764900ade8c129f309df263eb74", + "reference": "6be02650cc361764900ade8c129f309df263eb74", "shasum": "" }, "require": { "adhocore/jwt": "^1.1", "php": ">=8.0", - "utopia-php/cache": "^0.11.0", - "utopia-php/framework": "0.*.*" + "utopia-php/cache": "0.12.*", + "utopia-php/framework": "0.*.*", + "utopia-php/system": "0.9.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -2843,8 +4615,7 @@ "type": "library", "autoload": { "psr-4": { - "Utopia\\VCS\\": "src/VCS", - "Utopia\\Detector\\": "src/Detector" + "Utopia\\VCS\\": "src/VCS" } }, "notification-url": "https://packagist.org/downloads/", @@ -2860,33 +4631,34 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.8.3" + "source": "https://github.com/utopia-php/vcs/tree/0.10.1" }, - "time": "2024-11-05T17:10:09+00:00" + "time": "2025-03-18T11:44:09+00:00" }, { "name": "utopia-php/websocket", - "version": "0.1.0", + "version": "0.3.0", "source": { "type": "git", "url": "https://github.com/utopia-php/websocket.git", - "reference": "51fcb86171400d8aa40d76c54593481fd273dab5" + "reference": "629e53640b108eab43c7cc9ab375efade8622d43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/websocket/zipball/51fcb86171400d8aa40d76c54593481fd273dab5", - "reference": "51fcb86171400d8aa40d76c54593481fd273dab5", + "url": "https://api.github.com/repos/utopia-php/websocket/zipball/629e53640b108eab43c7cc9ab375efade8622d43", + "reference": "629e53640b108eab43c7cc9ab375efade8622d43", "shasum": "" }, "require": { "php": ">=8.0" }, "require-dev": { + "laravel/pint": "^1.15", + "phpstan/phpstan": "^1.12", "phpunit/phpunit": "^9.5.5", - "swoole/ide-helper": "4.6.6", + "swoole/ide-helper": "5.1.2", "textalk/websocket": "1.5.2", - "vimeo/psalm": "^4.8.1", - "workerman/workerman": "^4.0" + "workerman/workerman": "4.1.*" }, "type": "library", "autoload": { @@ -2898,16 +4670,6 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Eldad Fux", - "email": "eldad@appwrite.io" - }, - { - "name": "Torsten Dittmann", - "email": "torsten@appwrite.io" - } - ], "description": "A simple abstraction for WebSocket servers.", "keywords": [ "framework", @@ -2918,9 +4680,9 @@ ], "support": { "issues": "https://github.com/utopia-php/websocket/issues", - "source": "https://github.com/utopia-php/websocket/tree/0.1.0" + "source": "https://github.com/utopia-php/websocket/tree/0.3.0" }, - "time": "2021-12-20T10:50:09+00:00" + "time": "2025-03-28T01:11:13+00:00" }, { "name": "webmozart/assert", @@ -3049,16 +4811,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.24", + "version": "0.40.12", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "412451c87f6ef17e24e9a5cf41721043d74c60c8" + "reference": "182ec17848f81b78c336379bac94ff92b7a73365" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/412451c87f6ef17e24e9a5cf41721043d74c60c8", - "reference": "412451c87f6ef17e24e9a5cf41721043d74c60c8", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/182ec17848f81b78c336379bac94ff92b7a73365", + "reference": "182ec17848f81b78c336379bac94ff92b7a73365", "shasum": "" }, "require": { @@ -3066,7 +4828,7 @@ "ext-json": "*", "ext-mbstring": "*", "matthiasmullie/minify": "1.3.*", - "php": ">=8.0", + "php": ">=8.3", "twig/twig": "3.14.*" }, "require-dev": { @@ -3094,9 +4856,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.39.24" + "source": "https://github.com/appwrite/sdk-generator/tree/0.40.12" }, - "time": "2024-10-09T19:13:27+00:00" + "time": "2025-04-02T23:36:11+00:00" }, { "name": "doctrine/annotations", @@ -3174,79 +4936,32 @@ }, "time": "2024-09-05T10:17:24+00:00" }, - { - "name": "doctrine/deprecations", - "version": "1.1.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.3" - }, - "time": "2024-01-30T19:34:25+00:00" - }, { "name": "doctrine/instantiator", - "version": "1.5.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -3273,7 +4988,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -3289,7 +5004,7 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:15:36+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "doctrine/lexer", @@ -3370,16 +5085,16 @@ }, { "name": "laravel/pint", - "version": "v1.18.1", + "version": "v1.22.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9" + "reference": "7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/35c00c05ec43e6b46d295efc0f4386ceb30d50d9", - "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9", + "url": "https://api.github.com/repos/laravel/pint/zipball/7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36", + "reference": "7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36", "shasum": "" }, "require": { @@ -3387,16 +5102,16 @@ "ext-mbstring": "*", "ext-tokenizer": "*", "ext-xml": "*", - "php": "^8.1.0" + "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.64.0", - "illuminate/view": "^10.48.20", - "larastan/larastan": "^2.9.8", - "laravel-zero/framework": "^10.4.0", + "friendsofphp/php-cs-fixer": "^3.75.0", + "illuminate/view": "^11.44.2", + "larastan/larastan": "^3.3.1", + "laravel-zero/framework": "^11.36.1", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.35.1" + "nunomaduro/termwind": "^2.3", + "pestphp/pest": "^2.36.0" }, "bin": [ "builds/pint" @@ -3432,7 +5147,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-09-24T17:22:50+00:00" + "time": "2025-04-08T22:11:45+00:00" }, { "name": "matthiasmullie/minify", @@ -3560,16 +5275,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.1", + "version": "1.13.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" + "reference": "024473a478be9df5fdaca2c793f2232fe788e414" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", + "reference": "024473a478be9df5fdaca2c793f2232fe788e414", "shasum": "" }, "require": { @@ -3608,7 +5323,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" }, "funding": [ { @@ -3616,20 +5331,20 @@ "type": "tidelift" } ], - "time": "2024-11-08T17:47:46+00:00" + "time": "2025-02-12T12:17:51+00:00" }, { "name": "nikic/php-parser", - "version": "v5.3.1", + "version": "v5.4.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", - "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", "shasum": "" }, "require": { @@ -3672,9 +5387,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" }, - "time": "2024-10-08T18:51:32+00:00" + "time": "2024-12-30T11:07:19+00:00" }, { "name": "phar-io/manifest", @@ -3845,70 +5560,18 @@ }, "time": "2023-10-30T13:38:26+00:00" }, - { - "name": "phpbench/dom", - "version": "0.3.3", - "source": { - "type": "git", - "url": "https://github.com/phpbench/dom.git", - "reference": "786a96db538d0def931f5b19225233ec42ec7a72" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/dom/zipball/786a96db538d0def931f5b19225233ec42ec7a72", - "reference": "786a96db538d0def931f5b19225233ec42ec7a72", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": "^7.3||^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.14", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.0||^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\Dom\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "DOM wrapper to simplify working with the PHP DOM implementation", - "support": { - "issues": "https://github.com/phpbench/dom/issues", - "source": "https://github.com/phpbench/dom/tree/0.3.3" - }, - "abandoned": true, - "time": "2023-03-06T23:46:57+00:00" - }, { "name": "phpbench/phpbench", - "version": "1.3.1", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/phpbench/phpbench.git", - "reference": "a3e1ef08d9d7736d43a7fbd444893d6a073c0ca0" + "reference": "78cd98a9aa34e0f8f80ca01972a8b88d2c30194b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/a3e1ef08d9d7736d43a7fbd444893d6a073c0ca0", - "reference": "a3e1ef08d9d7736d43a7fbd444893d6a073c0ca0", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/78cd98a9aa34e0f8f80ca01972a8b88d2c30194b", + "reference": "78cd98a9aa34e0f8f80ca01972a8b88d2c30194b", "shasum": "" }, "require": { @@ -3921,7 +5584,6 @@ "ext-tokenizer": "*", "php": "^8.1", "phpbench/container": "^2.2", - "phpbench/dom": "~0.3.3", "psr/log": "^1.1 || ^2.0 || ^3.0", "seld/jsonlint": "^1.1", "symfony/console": "^6.1 || ^7.0", @@ -3940,8 +5602,8 @@ "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.0", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^10.4", - "rector/rector": "^0.18.11 || ^1.0.0", + "phpunit/phpunit": "^10.4 || ^11.0", + "rector/rector": "^1.2", "symfony/error-handler": "^6.1 || ^7.0", "symfony/var-dumper": "^6.1 || ^7.0" }, @@ -3986,7 +5648,7 @@ ], "support": { "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.3.1" + "source": "https://github.com/phpbench/phpbench/tree/1.4.1" }, "funding": [ { @@ -3994,298 +5656,66 @@ "type": "github" } ], - "time": "2024-06-30T11:04:37+00:00" + "time": "2025-03-12T08:01:40+00:00" }, { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", + "name": "phpstan/phpstan", + "version": "1.8.11", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + "url": "https://github.com/phpstan/phpstan.git", + "reference": "46e223dd68a620da18855c23046ddb00940b4014" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/46e223dd68a620da18855c23046ddb00940b4014", + "reference": "46e223dd68a620da18855c23046ddb00940b4014", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.2|^8.0" }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } + "files": [ + "bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", + "description": "PHPStan - PHP Static Analysis Tool", "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", + "dev", "static analysis" ], "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/1.8.11" }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.5.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "0c70d2c566e899666f367ab7b80986beb3581e6f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/0c70d2c566e899666f367ab7b80986beb3581e6f", - "reference": "0c70d2c566e899666f367ab7b80986beb3581e6f", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.1", - "ext-filter": "*", - "php": "^7.4 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.5 || ~1.6.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-webmozart-assert": "^1.2", - "phpunit/phpunit": "^9.5", - "psalm/phar": "^5.26" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "url": "https://github.com/ondrejmirtes", + "type": "github" }, { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.5.1" - }, - "time": "2024-11-06T11:58:54+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.3 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.18|^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" - }, - "time": "2024-11-09T15:12:26+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.19.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "67a759e7d8746d501c41536ba40cd9c0a07d6a87" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/67a759e7d8746d501c41536ba40cd9c0a07d6a87", - "reference": "67a759e7d8746d501c41536ba40cd9c0a07d6a87", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2 || ^2.0", - "php": "^7.2 || 8.0.* || 8.1.* || 8.2.* || 8.3.*", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0 || ^5.0 || ^6.0", - "sebastian/recursion-context": "^3.0 || ^4.0 || ^5.0 || ^6.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^8.0 || ^9.0 || ^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "url": "https://github.com/phpstan", + "type": "github" }, { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "dev", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.19.0" - }, - "time": "2024-02-29T11:52:51+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "1.33.0", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0" - }, - "time": "2024-10-13T11:25:22+00:00" + "time": "2022-10-24T15:45:13+00:00" }, { "name": "phpunit/php-code-coverage", @@ -4608,55 +6038,50 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.20", + "version": "9.6.22", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba" + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/12bc8879fb65aef2138b26fc633cb1e3620cffba", - "reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f80235cb4d3caa59ae09be3adf1ded27521d1a9c", + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.13", - "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-code-coverage": "^9.2.32", + "phpunit/php-file-iterator": "^3.0.6", "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.0", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", "sebastian/version": "^3.0.2" }, - "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" - }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -4664,7 +6089,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { @@ -4695,7 +6120,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.20" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.22" }, "funding": [ { @@ -4705,9 +6131,13 @@ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2022-04-01T12:37:26+00:00" + "time": "2024-12-05T13:48:26+00:00" }, { "name": "psr/cache", @@ -4758,109 +6188,6 @@ }, "time": "2021-02-03T23:26:27+00:00" }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "psr/log", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" - }, - "time": "2024-09-11T13:17:53+00:00" - }, { "name": "sebastian/cli-parser", "version": "1.0.2", @@ -5922,16 +7249,16 @@ }, { "name": "symfony/console", - "version": "v7.1.7", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3284aafcac338b6e86fd955ee4d794cbe434151a" + "reference": "e51498ea18570c062e7df29d05a7003585b19b88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3284aafcac338b6e86fd955ee4d794cbe434151a", - "reference": "3284aafcac338b6e86fd955ee4d794cbe434151a", + "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88", + "reference": "e51498ea18570c062e7df29d05a7003585b19b88", "shasum": "" }, "require": { @@ -5995,7 +7322,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.7" + "source": "https://github.com/symfony/console/tree/v7.2.5" }, "funding": [ { @@ -6011,87 +7338,20 @@ "type": "tidelift" } ], - "time": "2024-11-05T15:34:55+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "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.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2025-03-12T08:11:12+00:00" }, { "name": "symfony/filesystem", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4" + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/c835867b3c62bb05c7fe3d637c871c7ae52024d4", - "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", "shasum": "" }, "require": { @@ -6128,7 +7388,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.1.6" + "source": "https://github.com/symfony/filesystem/tree/v7.2.0" }, "funding": [ { @@ -6144,20 +7404,20 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:11:02+00:00" + "time": "2024-10-25T15:15:23+00:00" }, { "name": "symfony/finder", - "version": "v7.1.6", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" + "reference": "87a71856f2f56e4100373e92529eed3171695cfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", - "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", + "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb", "shasum": "" }, "require": { @@ -6192,7 +7452,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.6" + "source": "https://github.com/symfony/finder/tree/v7.2.2" }, "funding": [ { @@ -6208,20 +7468,20 @@ "type": "tidelift" } ], - "time": "2024-10-01T08:31:23+00:00" + "time": "2024-12-30T19:00:17+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "85e95eeede2d41cd146146e98c9c81d9214cae85" + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/85e95eeede2d41cd146146e98c9c81d9214cae85", - "reference": "85e95eeede2d41cd146146e98c9c81d9214cae85", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", "shasum": "" }, "require": { @@ -6259,7 +7519,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.1.6" + "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" }, "funding": [ { @@ -6275,7 +7535,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-20T11:17:29+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6303,8 +7563,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6379,8 +7639,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6457,8 +7717,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6535,8 +7795,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6593,16 +7853,16 @@ }, { "name": "symfony/process", - "version": "v7.1.7", + "version": "v7.2.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "9b8a40b7289767aa7117e957573c2a535efe6585" + "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/9b8a40b7289767aa7117e957573c2a535efe6585", - "reference": "9b8a40b7289767aa7117e957573c2a535efe6585", + "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", + "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", "shasum": "" }, "require": { @@ -6634,7 +7894,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.7" + "source": "https://github.com/symfony/process/tree/v7.2.5" }, "funding": [ { @@ -6650,103 +7910,20 @@ "type": "tidelift" } ], - "time": "2024-11-06T09:25:12+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2025-03-13T12:21:46+00:00" }, { "name": "symfony/string", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626" + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/61b72d66bf96c360a727ae6232df5ac83c71f626", - "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626", + "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", "shasum": "" }, "require": { @@ -6804,7 +7981,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.6" + "source": "https://github.com/symfony/string/tree/v7.2.0" }, "funding": [ { @@ -6820,20 +7997,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-13T13:31:26+00:00" }, { "name": "textalk/websocket", - "version": "1.5.7", + "version": "1.5.8", "source": { "type": "git", "url": "https://github.com/Textalk/websocket-php.git", - "reference": "1712325e99b6bf869ccbf9bf41ab749e7328ea46" + "reference": "d05dbaa97500176447ffb1f1800573f23085ab13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Textalk/websocket-php/zipball/1712325e99b6bf869ccbf9bf41ab749e7328ea46", - "reference": "1712325e99b6bf869ccbf9bf41ab749e7328ea46", + "url": "https://api.github.com/repos/Textalk/websocket-php/zipball/d05dbaa97500176447ffb1f1800573f23085ab13", + "reference": "d05dbaa97500176447ffb1f1800573f23085ab13", "shasum": "" }, "require": { @@ -6867,9 +8044,9 @@ "description": "WebSocket client and server", "support": { "issues": "https://github.com/Textalk/websocket-php/issues", - "source": "https://github.com/Textalk/websocket-php/tree/1.5.7" + "source": "https://github.com/Textalk/websocket-php/tree/1.5.8" }, - "time": "2022-03-29T09:46:59+00:00" + "time": "2022-04-26T06:28:24+00:00" }, { "name": "theseer/tokenizer", @@ -6923,16 +8100,16 @@ }, { "name": "twig/twig", - "version": "v3.14.1", + "version": "v3.14.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "f405356d20fb43603bcadc8b09bfb676cb04a379" + "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/f405356d20fb43603bcadc8b09bfb676cb04a379", - "reference": "f405356d20fb43603bcadc8b09bfb676cb04a379", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", + "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", "shasum": "" }, "require": { @@ -6986,7 +8163,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.14.1" + "source": "https://github.com/twigphp/Twig/tree/v3.14.2" }, "funding": [ { @@ -6998,7 +8175,7 @@ "type": "tidelift" } ], - "time": "2024-11-06T18:17:38+00:00" + "time": "2024-11-07T12:36:22+00:00" }, { "name": "webmozart/glob", @@ -7052,7 +8229,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -7076,5 +8253,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/docker-compose.yml b/docker-compose.yml index 048178e60a..51cb511f17 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -72,10 +72,13 @@ services: - traefik.http.routers.appwrite_api_https.tls=true volumes: - appwrite-uploads:/storage/uploads:rw + - appwrite-imports:/storage/imports:rw - appwrite-cache:/storage/cache:rw - appwrite-config:/storage/config:rw - appwrite-certificates:/storage/certificates:rw - appwrite-functions:/storage/functions:rw + - appwrite-sites:/storage/sites:rw + - appwrite-builds:/storage/builds:rw - ./phpunit.xml:/usr/src/code/phpunit.xml - ./tests:/usr/src/code/tests - ./app:/usr/src/code/app @@ -110,10 +113,12 @@ services: - _APP_OPTIONS_ABUSE - _APP_OPTIONS_ROUTER_PROTECTION - _APP_OPTIONS_FORCE_HTTPS - - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS + - _APP_OPTIONS_ROUTER_FORCE_HTTPS - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - - _APP_DOMAIN_TARGET + - _APP_DOMAIN_TARGET_CNAME + - _APP_DOMAIN_TARGET_AAAA + - _APP_DOMAIN_TARGET_A - _APP_DOMAIN_FUNCTIONS - _APP_REDIS_HOST - _APP_REDIS_PORT @@ -140,6 +145,7 @@ services: - _APP_STORAGE_S3_SECRET - _APP_STORAGE_S3_REGION - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_S3_ENDPOINT - _APP_STORAGE_DO_SPACES_ACCESS_KEY - _APP_STORAGE_DO_SPACES_SECRET - _APP_STORAGE_DO_SPACES_REGION @@ -156,12 +162,15 @@ services: - _APP_STORAGE_WASABI_SECRET - _APP_STORAGE_WASABI_REGION - _APP_STORAGE_WASABI_BUCKET - - _APP_FUNCTIONS_SIZE_LIMIT + - _APP_COMPUTE_SIZE_LIMIT - _APP_FUNCTIONS_TIMEOUT - - _APP_FUNCTIONS_BUILD_TIMEOUT - - _APP_FUNCTIONS_CPUS - - _APP_FUNCTIONS_MEMORY + - _APP_SITES_TIMEOUT + - _APP_COMPUTE_BUILD_TIMEOUT + - _APP_COMPUTE_CPUS + - _APP_COMPUTE_MEMORY - _APP_FUNCTIONS_RUNTIMES + - _APP_SITES_RUNTIMES + - _APP_DOMAIN_SITES - _APP_EXECUTOR_SECRET - _APP_EXECUTOR_HOST - _APP_LOGGING_CONFIG @@ -170,6 +179,7 @@ services: - _APP_MAINTENANCE_RETENTION_CACHE - _APP_MAINTENANCE_RETENTION_ABUSE - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY - _APP_MAINTENANCE_RETENTION_SCHEDULES - _APP_SMS_PROVIDER @@ -193,11 +203,16 @@ services: - _APP_EXPERIMENT_LOGGING_PROVIDER - _APP_EXPERIMENT_LOGGING_CONFIG - _APP_DATABASE_SHARED_TABLES + - _APP_DATABASE_SHARED_TABLES_V1 + - _APP_DATABASE_SHARED_NAMESPACE + - _APP_FUNCTIONS_CREATION_ABUSE_LIMIT + extra_hosts: + - "host.docker.internal:host-gateway" appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:5.0.12 + image: appwrite/console:5.3.0-sites-rc.40 restart: unless-stopped networks: - appwrite @@ -340,6 +355,7 @@ services: - appwrite-uploads:/storage/uploads:rw - appwrite-cache:/storage/cache:rw - appwrite-functions:/storage/functions:rw + - appwrite-sites:/storage/sites:rw - appwrite-builds:/storage/builds:rw - appwrite-certificates:/storage/certificates:rw - ./app:/usr/src/code/app @@ -362,6 +378,7 @@ services: - _APP_STORAGE_S3_SECRET - _APP_STORAGE_S3_REGION - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_S3_ENDPOINT - _APP_STORAGE_DO_SPACES_ACCESS_KEY - _APP_STORAGE_DO_SPACES_SECRET - _APP_STORAGE_DO_SPACES_REGION @@ -382,6 +399,10 @@ services: - _APP_EXECUTOR_SECRET - _APP_EXECUTOR_HOST - _APP_DATABASE_SHARED_TABLES + - _APP_DATABASE_SHARED_TABLES_V1 + - _APP_EMAIL_CERTIFICATES + - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE appwrite-worker-databases: entrypoint: worker-databases @@ -423,7 +444,9 @@ services: - appwrite volumes: - appwrite-functions:/storage/functions:rw + - appwrite-sites:/storage/sites:rw - appwrite-builds:/storage/builds:rw + - appwrite-uploads:/storage/uploads:rw - ./app:/usr/src/code/app - ./src:/usr/src/code/src depends_on: @@ -449,18 +472,20 @@ services: - _APP_VCS_GITHUB_PRIVATE_KEY - _APP_VCS_GITHUB_APP_ID - _APP_FUNCTIONS_TIMEOUT - - _APP_FUNCTIONS_BUILD_TIMEOUT - - _APP_FUNCTIONS_CPUS - - _APP_FUNCTIONS_MEMORY - - _APP_FUNCTIONS_SIZE_LIMIT + - _APP_SITES_TIMEOUT + - _APP_COMPUTE_BUILD_TIMEOUT + - _APP_COMPUTE_CPUS + - _APP_COMPUTE_MEMORY + - _APP_COMPUTE_SIZE_LIMIT - _APP_OPTIONS_FORCE_HTTPS - - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS + - _APP_OPTIONS_ROUTER_FORCE_HTTPS - _APP_DOMAIN - _APP_STORAGE_DEVICE - _APP_STORAGE_S3_ACCESS_KEY - _APP_STORAGE_S3_SECRET - _APP_STORAGE_S3_REGION - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_S3_ENDPOINT - _APP_STORAGE_DO_SPACES_ACCESS_KEY - _APP_STORAGE_DO_SPACES_SECRET - _APP_STORAGE_DO_SPACES_REGION @@ -478,6 +503,9 @@ services: - _APP_STORAGE_WASABI_REGION - _APP_STORAGE_WASABI_BUCKET - _APP_DATABASE_SHARED_TABLES + - _APP_DOMAIN_SITES + extra_hosts: + - "host.docker.internal:host-gateway" appwrite-worker-certificates: entrypoint: worker-certificates @@ -499,7 +527,9 @@ services: - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - - _APP_DOMAIN_TARGET + - _APP_DOMAIN_TARGET_CNAME + - _APP_DOMAIN_TARGET_AAAA + - _APP_DOMAIN_TARGET_A - _APP_DOMAIN_FUNCTIONS - _APP_EMAIL_CERTIFICATES - _APP_REDIS_HOST @@ -544,9 +574,10 @@ services: - _APP_DB_USER - _APP_DB_PASS - _APP_FUNCTIONS_TIMEOUT - - _APP_FUNCTIONS_BUILD_TIMEOUT - - _APP_FUNCTIONS_CPUS - - _APP_FUNCTIONS_MEMORY + - _APP_SITES_TIMEOUT + - _APP_COMPUTE_BUILD_TIMEOUT + - _APP_COMPUTE_CPUS + - _APP_COMPUTE_MEMORY - _APP_EXECUTOR_SECRET - _APP_EXECUTOR_HOST - _APP_USAGE_STATS @@ -626,6 +657,7 @@ services: - _APP_STORAGE_S3_SECRET - _APP_STORAGE_S3_REGION - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_S3_ENDPOINT - _APP_STORAGE_DO_SPACES_ACCESS_KEY - _APP_STORAGE_DO_SPACES_SECRET - _APP_STORAGE_DO_SPACES_REGION @@ -653,6 +685,7 @@ services: networks: - appwrite volumes: + - appwrite-imports:/storage/imports:rw - ./app:/usr/src/code/app - ./src:/usr/src/code/src - ./tests:/usr/src/code/tests @@ -663,7 +696,9 @@ services: - _APP_WORKER_PER_CORE - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - - _APP_DOMAIN_TARGET + - _APP_DOMAIN_TARGET_CNAME + - _APP_DOMAIN_TARGET_AAAA + - _APP_DOMAIN_TARGET_A - _APP_EMAIL_SECURITY - _APP_REDIS_HOST - _APP_REDIS_PORT @@ -695,7 +730,9 @@ services: - _APP_ENV - _APP_WORKER_PER_CORE - _APP_DOMAIN - - _APP_DOMAIN_TARGET + - _APP_DOMAIN_TARGET_CNAME + - _APP_DOMAIN_TARGET_AAAA + - _APP_DOMAIN_TARGET_A - _APP_DOMAIN_FUNCTIONS - _APP_OPENSSL_KEY_V1 - _APP_REDIS_HOST @@ -712,15 +749,47 @@ services: - _APP_MAINTENANCE_RETENTION_CACHE - _APP_MAINTENANCE_RETENTION_ABUSE - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY - _APP_MAINTENANCE_RETENTION_SCHEDULES - _APP_MAINTENANCE_DELAY - _APP_DATABASE_SHARED_TABLES - appwrite-worker-usage: - entrypoint: worker-usage + appwrite-task-stats-resources: + container_name: appwrite-task-stats-resources + entrypoint: stats-resources <<: *x-logging - container_name: appwrite-worker-usage + image: appwrite-dev + networks: + - appwrite + volumes: + - ./app:/usr/src/code/app + - ./src:/usr/src/code/src + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_USAGE_STATS + - _APP_LOGGING_CONFIG + - _APP_DATABASE_SHARED_TABLES + - _APP_STATS_RESOURCES_INTERVAL + + appwrite-worker-stats-resources: + entrypoint: worker-stats-resources + <<: *x-logging + container_name: appwrite-worker-stats-resources image: appwrite-dev networks: - appwrite @@ -748,10 +817,10 @@ services: - _APP_USAGE_AGGREGATION_INTERVAL - _APP_DATABASE_SHARED_TABLES - appwrite-worker-usage-dump: - entrypoint: worker-usage-dump + appwrite-worker-stats-usage: + entrypoint: worker-stats-usage <<: *x-logging - container_name: appwrite-worker-usage-dump + container_name: appwrite-worker-stats-usage image: appwrite-dev networks: - appwrite @@ -779,6 +848,38 @@ services: - _APP_USAGE_AGGREGATION_INTERVAL - _APP_DATABASE_SHARED_TABLES + appwrite-worker-stats-usage-dump: + entrypoint: worker-stats-usage-dump + <<: *x-logging + container_name: appwrite-worker-stats-usage-dump + image: appwrite-dev + networks: + - appwrite + volumes: + - ./app:/usr/src/code/app + - ./src:/usr/src/code/src + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_USAGE_STATS + - _APP_LOGGING_CONFIG + - _APP_USAGE_AGGREGATION_INTERVAL + - _APP_DATABASE_SHARED_TABLES + - _APP_STATS_USAGE_DUAL_WRITING_DBS + appwrite-task-scheduler-functions: entrypoint: schedule-functions <<: *x-logging @@ -864,18 +965,24 @@ services: appwrite-assistant: container_name: appwrite-assistant - image: appwrite/assistant:0.5.0 + image: appwrite/assistant:0.7.0 networks: - appwrite environment: - _APP_ASSISTANT_OPENAI_API_KEY + appwrite-browser: + container_name: appwrite-browser + image: appwrite/browser:0.2.2 + networks: + - appwrite + openruntimes-executor: container_name: openruntimes-executor hostname: exc1 <<: *x-logging stop_signal: SIGINT - image: openruntimes/executor:0.6.11 + image: openruntimes/executor:0.7.13 restart: unless-stopped networks: - appwrite @@ -884,25 +991,28 @@ services: - /var/run/docker.sock:/var/run/docker.sock - appwrite-builds:/storage/builds:rw - appwrite-functions:/storage/functions:rw + - appwrite-sites:/storage/sites:rw # Host mount nessessary to share files between executor and runtimes. # It's not possible to share mount file between 2 containers without host mount (copying is too slow) - /tmp:/tmp:rw environment: - - OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD - - OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL - - OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK + - OPR_EXECUTOR_IMAGE_PULL=enabled + - OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_COMPUTE_INACTIVE_THRESHOLD + - OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_COMPUTE_MAINTENANCE_INTERVAL + - OPR_EXECUTOR_NETWORK=$_APP_COMPUTE_RUNTIMES_NETWORK - OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME - OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD - OPR_EXECUTOR_ENV=$_APP_ENV - - OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES + - OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES,$_APP_SITES_RUNTIMES - OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET - - OPR_EXECUTOR_RUNTIME_VERSIONS=v2,v4 + - OPR_EXECUTOR_RUNTIME_VERSIONS=v2,v5 - OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG - OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE - OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY - OPR_EXECUTOR_STORAGE_S3_SECRET=$_APP_STORAGE_S3_SECRET - OPR_EXECUTOR_STORAGE_S3_REGION=$_APP_STORAGE_S3_REGION - OPR_EXECUTOR_STORAGE_S3_BUCKET=$_APP_STORAGE_S3_BUCKET + - OPR_EXECUTOR_STORAGE_S3_ENDPOINT=$_APP_STORAGE_S3_ENDPOINT - OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=$_APP_STORAGE_DO_SPACES_ACCESS_KEY - OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=$_APP_STORAGE_DO_SPACES_SECRET - OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=$_APP_STORAGE_DO_SPACES_REGION @@ -1051,7 +1161,9 @@ volumes: appwrite-redis: appwrite-cache: appwrite-uploads: + appwrite-imports: appwrite-certificates: appwrite-functions: + appwrite-sites: appwrite-builds: - appwrite-config: \ No newline at end of file + appwrite-config: diff --git a/docs/examples/1.6.x/client-android/java/functions/get-deployment-download.md b/docs/examples/1.6.x/client-android/java/functions/get-deployment-download.md deleted file mode 100644 index 200cdf2fc5..0000000000 --- a/docs/examples/1.6.x/client-android/java/functions/get-deployment-download.md +++ /dev/null @@ -1,23 +0,0 @@ -import io.appwrite.Client; -import io.appwrite.coroutines.CoroutineCallback; -import io.appwrite.services.Functions; - -Client client = new Client(context) - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject(""); // Your project ID - -Functions functions = new Functions(client); - -functions.getDeploymentDownload( - "", // functionId - "", // deploymentId - new CoroutineCallback<>((result, error) -> { - if (error != null) { - error.printStackTrace(); - return; - } - - Log.d("Appwrite", result.toString()); - }) -); - diff --git a/docs/examples/1.6.x/client-android/java/functions/get-template.md b/docs/examples/1.6.x/client-android/java/functions/get-template.md deleted file mode 100644 index af9efc7b92..0000000000 --- a/docs/examples/1.6.x/client-android/java/functions/get-template.md +++ /dev/null @@ -1,22 +0,0 @@ -import io.appwrite.Client; -import io.appwrite.coroutines.CoroutineCallback; -import io.appwrite.services.Functions; - -Client client = new Client(context) - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject(""); // Your project ID - -Functions functions = new Functions(client); - -functions.getTemplate( - "", // templateId - new CoroutineCallback<>((result, error) -> { - if (error != null) { - error.printStackTrace(); - return; - } - - Log.d("Appwrite", result.toString()); - }) -); - diff --git a/docs/examples/1.6.x/client-android/java/functions/list-templates.md b/docs/examples/1.6.x/client-android/java/functions/list-templates.md deleted file mode 100644 index 6c051f3b04..0000000000 --- a/docs/examples/1.6.x/client-android/java/functions/list-templates.md +++ /dev/null @@ -1,25 +0,0 @@ -import io.appwrite.Client; -import io.appwrite.coroutines.CoroutineCallback; -import io.appwrite.services.Functions; - -Client client = new Client(context) - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject(""); // Your project ID - -Functions functions = new Functions(client); - -functions.listTemplates( - listOf(), // runtimes (optional) - listOf(), // useCases (optional) - 1, // limit (optional) - 0, // offset (optional) - new CoroutineCallback<>((result, error) -> { - if (error != null) { - error.printStackTrace(); - return; - } - - Log.d("Appwrite", result.toString()); - }) -); - diff --git a/docs/examples/1.6.x/client-android/kotlin/functions/get-deployment-download.md b/docs/examples/1.6.x/client-android/kotlin/functions/get-deployment-download.md deleted file mode 100644 index 21e99cb731..0000000000 --- a/docs/examples/1.6.x/client-android/kotlin/functions/get-deployment-download.md +++ /dev/null @@ -1,14 +0,0 @@ -import io.appwrite.Client -import io.appwrite.coroutines.CoroutineCallback -import io.appwrite.services.Functions - -val client = Client(context) - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("") // Your project ID - -val functions = Functions(client) - -val result = functions.getDeploymentDownload( - functionId = "", - deploymentId = "", -) \ No newline at end of file diff --git a/docs/examples/1.6.x/client-android/kotlin/functions/get-template.md b/docs/examples/1.6.x/client-android/kotlin/functions/get-template.md deleted file mode 100644 index 4af83bda3e..0000000000 --- a/docs/examples/1.6.x/client-android/kotlin/functions/get-template.md +++ /dev/null @@ -1,13 +0,0 @@ -import io.appwrite.Client -import io.appwrite.coroutines.CoroutineCallback -import io.appwrite.services.Functions - -val client = Client(context) - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("") // Your project ID - -val functions = Functions(client) - -val result = functions.getTemplate( - templateId = "", -) \ No newline at end of file diff --git a/docs/examples/1.6.x/client-android/kotlin/functions/list-templates.md b/docs/examples/1.6.x/client-android/kotlin/functions/list-templates.md deleted file mode 100644 index a1a59d9438..0000000000 --- a/docs/examples/1.6.x/client-android/kotlin/functions/list-templates.md +++ /dev/null @@ -1,16 +0,0 @@ -import io.appwrite.Client -import io.appwrite.coroutines.CoroutineCallback -import io.appwrite.services.Functions - -val client = Client(context) - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("") // Your project ID - -val functions = Functions(client) - -val result = functions.listTemplates( - runtimes = listOf(), // (optional) - useCases = listOf(), // (optional) - limit = 1, // (optional) - offset = 0, // (optional) -) \ No newline at end of file diff --git a/docs/examples/1.6.x/client-apple/examples/account/update-mfa-challenge.md b/docs/examples/1.6.x/client-apple/examples/account/update-mfa-challenge.md index a237537ae3..1c5874f784 100644 --- a/docs/examples/1.6.x/client-apple/examples/account/update-mfa-challenge.md +++ b/docs/examples/1.6.x/client-apple/examples/account/update-mfa-challenge.md @@ -6,7 +6,7 @@ let client = Client() let account = Account(client) -let result = try await account.updateMfaChallenge( +let session = try await account.updateMfaChallenge( challengeId: "", otp: "" ) diff --git a/docs/examples/1.6.x/client-apple/examples/functions/get-deployment-download.md b/docs/examples/1.6.x/client-apple/examples/functions/get-deployment-download.md deleted file mode 100644 index 0e6659969c..0000000000 --- a/docs/examples/1.6.x/client-apple/examples/functions/get-deployment-download.md +++ /dev/null @@ -1,13 +0,0 @@ -import Appwrite - -let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("") // Your project ID - -let functions = Functions(client) - -let bytes = try await functions.getDeploymentDownload( - functionId: "", - deploymentId: "" -) - diff --git a/docs/examples/1.6.x/client-apple/examples/functions/get-template.md b/docs/examples/1.6.x/client-apple/examples/functions/get-template.md deleted file mode 100644 index bc7a9a3aef..0000000000 --- a/docs/examples/1.6.x/client-apple/examples/functions/get-template.md +++ /dev/null @@ -1,12 +0,0 @@ -import Appwrite - -let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("") // Your project ID - -let functions = Functions(client) - -let templateFunction = try await functions.getTemplate( - templateId: "" -) - diff --git a/docs/examples/1.6.x/client-apple/examples/functions/list-templates.md b/docs/examples/1.6.x/client-apple/examples/functions/list-templates.md deleted file mode 100644 index d0090ab803..0000000000 --- a/docs/examples/1.6.x/client-apple/examples/functions/list-templates.md +++ /dev/null @@ -1,15 +0,0 @@ -import Appwrite - -let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("") // Your project ID - -let functions = Functions(client) - -let templateFunctionList = try await functions.listTemplates( - runtimes: [], // optional - useCases: [], // optional - limit: 1, // optional - offset: 0 // optional -) - diff --git a/docs/examples/1.6.x/client-flutter/examples/account/update-mfa-challenge.md b/docs/examples/1.6.x/client-flutter/examples/account/update-mfa-challenge.md index c8e1af7e90..bbe7c03470 100644 --- a/docs/examples/1.6.x/client-flutter/examples/account/update-mfa-challenge.md +++ b/docs/examples/1.6.x/client-flutter/examples/account/update-mfa-challenge.md @@ -6,7 +6,7 @@ Client client = Client() Account account = Account(client); - result = await account.updateMfaChallenge( +Session result = await account.updateMfaChallenge( challengeId: '', otp: '', ); diff --git a/docs/examples/1.6.x/client-flutter/examples/functions/get-deployment-download.md b/docs/examples/1.6.x/client-flutter/examples/functions/get-deployment-download.md deleted file mode 100644 index bb0ee903df..0000000000 --- a/docs/examples/1.6.x/client-flutter/examples/functions/get-deployment-download.md +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:appwrite/appwrite.dart'; - -Client client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject(''); // Your project ID - -Functions functions = Functions(client); - -// Downloading file -UInt8List bytes = await functions.getDeploymentDownload( - functionId: '', - deploymentId: '', -) - -final file = File('path_to_file/filename.ext'); -file.writeAsBytesSync(bytes); - -// Displaying image preview -FutureBuilder( - future: functions.getDeploymentDownload( - functionId:'' , - deploymentId:'' , -), // Works for both public file and private file, for private files you need to be logged in - builder: (context, snapshot) { - return snapshot.hasData && snapshot.data != null - ? Image.memory(snapshot.data) - : CircularProgressIndicator(); - } -); diff --git a/docs/examples/1.6.x/client-flutter/examples/functions/get-template.md b/docs/examples/1.6.x/client-flutter/examples/functions/get-template.md deleted file mode 100644 index 560a4d94ed..0000000000 --- a/docs/examples/1.6.x/client-flutter/examples/functions/get-template.md +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:appwrite/appwrite.dart'; - -Client client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject(''); // Your project ID - -Functions functions = Functions(client); - -TemplateFunction result = await functions.getTemplate( - templateId: '', -); diff --git a/docs/examples/1.6.x/client-flutter/examples/functions/list-templates.md b/docs/examples/1.6.x/client-flutter/examples/functions/list-templates.md deleted file mode 100644 index d3d8c7aa4c..0000000000 --- a/docs/examples/1.6.x/client-flutter/examples/functions/list-templates.md +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:appwrite/appwrite.dart'; - -Client client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject(''); // Your project ID - -Functions functions = Functions(client); - -TemplateFunctionList result = await functions.listTemplates( - runtimes: [], // optional - useCases: [], // optional - limit: 1, // optional - offset: 0, // optional -); diff --git a/docs/examples/1.6.x/client-graphql/examples/account/create-push-target.md b/docs/examples/1.6.x/client-graphql/examples/account/create-push-target.md index 8a0fad387c..63802a782e 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/create-push-target.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/create-push-target.md @@ -12,5 +12,6 @@ mutation { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/create.md b/docs/examples/1.6.x/client-graphql/examples/account/create.md index 3f8e3c3cf7..0d39394a3d 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/create.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/create.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/get.md b/docs/examples/1.6.x/client-graphql/examples/account/get.md index e4db8f0e41..f4f07c187f 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/get.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/get.md @@ -28,6 +28,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-email.md b/docs/examples/1.6.x/client-graphql/examples/account/update-email.md index b207bad4bb..c879e24a43 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-email.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-email.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-m-f-a.md b/docs/examples/1.6.x/client-graphql/examples/account/update-m-f-a.md index d2cd3d6ae5..787c2e0860 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-m-f-a.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-m-f-a.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-authenticator.md b/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-authenticator.md index c74062c7d4..9cfe9150be 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-authenticator.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-authenticator.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-challenge.md b/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-challenge.md index 8237431bcf..0bcec2157f 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-challenge.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-mfa-challenge.md @@ -3,6 +3,34 @@ mutation { challengeId: "", otp: "" ) { - status + _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 } } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-name.md b/docs/examples/1.6.x/client-graphql/examples/account/update-name.md index 850b5760a0..8ba2c99d9c 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-name.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-name.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-password.md b/docs/examples/1.6.x/client-graphql/examples/account/update-password.md index 5904da0842..f3619a10d2 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-password.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-password.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-phone.md b/docs/examples/1.6.x/client-graphql/examples/account/update-phone.md index 408a203300..adecb71168 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-phone.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-phone.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-prefs.md b/docs/examples/1.6.x/client-graphql/examples/account/update-prefs.md index 40db7b43db..57280247e4 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-prefs.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-prefs.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-push-target.md b/docs/examples/1.6.x/client-graphql/examples/account/update-push-target.md index 059702dc97..3c402cdf12 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-push-target.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-push-target.md @@ -11,5 +11,6 @@ mutation { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/client-graphql/examples/account/update-status.md b/docs/examples/1.6.x/client-graphql/examples/account/update-status.md index aca8c098e7..c17f556842 100644 --- a/docs/examples/1.6.x/client-graphql/examples/account/update-status.md +++ b/docs/examples/1.6.x/client-graphql/examples/account/update-status.md @@ -28,6 +28,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/client-graphql/examples/functions/get-deployment-download.md b/docs/examples/1.6.x/client-graphql/examples/functions/get-deployment-download.md deleted file mode 100644 index 396047bb94..0000000000 --- a/docs/examples/1.6.x/client-graphql/examples/functions/get-deployment-download.md +++ /dev/null @@ -1,8 +0,0 @@ -query { - functionsGetDeploymentDownload( - functionId: "", - deploymentId: "" - ) { - status - } -} diff --git a/docs/examples/1.6.x/client-graphql/examples/functions/get-template.md b/docs/examples/1.6.x/client-graphql/examples/functions/get-template.md deleted file mode 100644 index 44a466de27..0000000000 --- a/docs/examples/1.6.x/client-graphql/examples/functions/get-template.md +++ /dev/null @@ -1,35 +0,0 @@ -query { - functionsGetTemplate( - templateId: "" - ) { - icon - id - name - tagline - permissions - events - cron - timeout - useCases - runtimes { - name - commands - entrypoint - providerRootDirectory - } - instructions - vcsProvider - providerRepositoryId - providerOwner - providerVersion - variables { - name - description - value - placeholder - required - type - } - scopes - } -} diff --git a/docs/examples/1.6.x/client-graphql/examples/functions/list-templates.md b/docs/examples/1.6.x/client-graphql/examples/functions/list-templates.md deleted file mode 100644 index cb289ddabb..0000000000 --- a/docs/examples/1.6.x/client-graphql/examples/functions/list-templates.md +++ /dev/null @@ -1,41 +0,0 @@ -query { - functionsListTemplates( - runtimes: [], - useCases: [], - limit: 1, - offset: 0 - ) { - total - templates { - icon - id - name - tagline - permissions - events - cron - timeout - useCases - runtimes { - name - commands - entrypoint - providerRootDirectory - } - instructions - vcsProvider - providerRepositoryId - providerOwner - providerVersion - variables { - name - description - value - placeholder - required - type - } - scopes - } - } -} diff --git a/docs/examples/1.6.x/client-graphql/examples/messaging/create-subscriber.md b/docs/examples/1.6.x/client-graphql/examples/messaging/create-subscriber.md index b2712ebb48..bab53612b7 100644 --- a/docs/examples/1.6.x/client-graphql/examples/messaging/create-subscriber.md +++ b/docs/examples/1.6.x/client-graphql/examples/messaging/create-subscriber.md @@ -17,6 +17,7 @@ mutation { providerId providerType identifier + expired } userId userName diff --git a/docs/examples/1.6.x/client-react-native/examples/functions/get-deployment-download.md b/docs/examples/1.6.x/client-react-native/examples/functions/get-deployment-download.md deleted file mode 100644 index 7eac2b753f..0000000000 --- a/docs/examples/1.6.x/client-react-native/examples/functions/get-deployment-download.md +++ /dev/null @@ -1,14 +0,0 @@ -import { Client, Functions } from "react-native-appwrite"; - -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 -); - -console.log(result); diff --git a/docs/examples/1.6.x/client-react-native/examples/functions/get-template.md b/docs/examples/1.6.x/client-react-native/examples/functions/get-template.md deleted file mode 100644 index ea756323dc..0000000000 --- a/docs/examples/1.6.x/client-react-native/examples/functions/get-template.md +++ /dev/null @@ -1,13 +0,0 @@ -import { Client, Functions } from "react-native-appwrite"; - -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.6.x/client-react-native/examples/functions/list-templates.md b/docs/examples/1.6.x/client-react-native/examples/functions/list-templates.md deleted file mode 100644 index 3811dd8e40..0000000000 --- a/docs/examples/1.6.x/client-react-native/examples/functions/list-templates.md +++ /dev/null @@ -1,16 +0,0 @@ -import { Client, Functions } from "react-native-appwrite"; - -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.6.x/client-rest/examples/functions/get-deployment-download.md b/docs/examples/1.6.x/client-rest/examples/functions/get-deployment-download.md deleted file mode 100644 index 0f6166b77f..0000000000 --- a/docs/examples/1.6.x/client-rest/examples/functions/get-deployment-download.md +++ /dev/null @@ -1,8 +0,0 @@ -GET /v1/functions/{functionId}/deployments/{deploymentId}/download HTTP/1.1 -Host: cloud.appwrite.io -Content-Type: application/json -X-Appwrite-Response-Format: 1.6.0 -X-Appwrite-Project: -X-Appwrite-Session: -X-Appwrite-JWT: - diff --git a/docs/examples/1.6.x/client-rest/examples/functions/get-template.md b/docs/examples/1.6.x/client-rest/examples/functions/get-template.md deleted file mode 100644 index d4e1f95cf5..0000000000 --- a/docs/examples/1.6.x/client-rest/examples/functions/get-template.md +++ /dev/null @@ -1,6 +0,0 @@ -GET /v1/functions/templates/{templateId} HTTP/1.1 -Host: cloud.appwrite.io -Content-Type: application/json -X-Appwrite-Response-Format: 1.6.0 -X-Appwrite-Project: - diff --git a/docs/examples/1.6.x/client-rest/examples/functions/list-templates.md b/docs/examples/1.6.x/client-rest/examples/functions/list-templates.md deleted file mode 100644 index b671bedebf..0000000000 --- a/docs/examples/1.6.x/client-rest/examples/functions/list-templates.md +++ /dev/null @@ -1,6 +0,0 @@ -GET /v1/functions/templates HTTP/1.1 -Host: cloud.appwrite.io -Content-Type: application/json -X-Appwrite-Response-Format: 1.6.0 -X-Appwrite-Project: - diff --git a/docs/examples/1.6.x/client-web/examples/functions/get-deployment-download.md b/docs/examples/1.6.x/client-web/examples/functions/get-deployment-download.md deleted file mode 100644 index 62e3ee6551..0000000000 --- a/docs/examples/1.6.x/client-web/examples/functions/get-deployment-download.md +++ /dev/null @@ -1,14 +0,0 @@ -import { Client, Functions } from "appwrite"; - -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 -); - -console.log(result); diff --git a/docs/examples/1.6.x/client-web/examples/functions/get-template.md b/docs/examples/1.6.x/client-web/examples/functions/get-template.md deleted file mode 100644 index dd2d20284e..0000000000 --- a/docs/examples/1.6.x/client-web/examples/functions/get-template.md +++ /dev/null @@ -1,13 +0,0 @@ -import { Client, Functions } from "appwrite"; - -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.6.x/client-web/examples/functions/list-templates.md b/docs/examples/1.6.x/client-web/examples/functions/list-templates.md deleted file mode 100644 index 141c56322b..0000000000 --- a/docs/examples/1.6.x/client-web/examples/functions/list-templates.md +++ /dev/null @@ -1,16 +0,0 @@ -import { Client, Functions } from "appwrite"; - -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.6.x/console-cli/examples/databases/update-boolean-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-boolean-attribute.md index d48c3470fe..f5adb497ec 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-boolean-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-boolean-attribute.md @@ -3,4 +3,5 @@ appwrite databases updateBooleanAttribute \ --collectionId \ --key '' \ --required false \ - --default false + --default false \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-datetime-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-datetime-attribute.md index 9fc56373ed..fe4a462664 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-datetime-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-datetime-attribute.md @@ -3,4 +3,5 @@ appwrite databases updateDatetimeAttribute \ --collectionId \ --key '' \ --required false \ - --default '' + --default '' \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-email-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-email-attribute.md index 9f7bffeb9c..58510a6f8e 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-email-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-email-attribute.md @@ -3,4 +3,5 @@ appwrite databases updateEmailAttribute \ --collectionId \ --key '' \ --required false \ - --default email@example.com + --default email@example.com \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-enum-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-enum-attribute.md index bf562a0a82..21d56d3e64 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-enum-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-enum-attribute.md @@ -4,4 +4,5 @@ appwrite databases updateEnumAttribute \ --key '' \ --elements one two three \ --required false \ - --default + --default \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-float-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-float-attribute.md index 097dfd310a..353320d78a 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-float-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-float-attribute.md @@ -5,4 +5,5 @@ appwrite databases updateFloatAttribute \ --required false \ --min null \ --max null \ - --default null + --default null \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-integer-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-integer-attribute.md index 6a6b0747a8..c170b7f6fa 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-integer-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-integer-attribute.md @@ -5,4 +5,5 @@ appwrite databases updateIntegerAttribute \ --required false \ --min null \ --max null \ - --default null + --default null \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-ip-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-ip-attribute.md index 2439b5a8de..a400eadc1e 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-ip-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-ip-attribute.md @@ -3,4 +3,5 @@ appwrite databases updateIpAttribute \ --collectionId \ --key '' \ --required false \ - --default '' + --default '' \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-relationship-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-relationship-attribute.md index be03a70736..6e2dbd927d 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-relationship-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-relationship-attribute.md @@ -3,3 +3,4 @@ appwrite databases updateRelationshipAttribute \ --collectionId \ --key '' \ + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-string-attribute.md index ebf45253fa..526ece0b72 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-string-attribute.md @@ -3,4 +3,6 @@ appwrite databases updateStringAttribute \ --collectionId \ --key '' \ --required false \ - --default + --default \ + + diff --git a/docs/examples/1.6.x/console-cli/examples/databases/update-url-attribute.md b/docs/examples/1.6.x/console-cli/examples/databases/update-url-attribute.md index aa11a588db..e6f401b8ca 100644 --- a/docs/examples/1.6.x/console-cli/examples/databases/update-url-attribute.md +++ b/docs/examples/1.6.x/console-cli/examples/databases/update-url-attribute.md @@ -3,4 +3,5 @@ appwrite databases updateUrlAttribute \ --collectionId \ --key '' \ --required false \ - --default https://example.com + --default https://example.com \ + diff --git a/docs/examples/1.6.x/console-cli/examples/functions/download-deployment.md b/docs/examples/1.6.x/console-cli/examples/functions/download-deployment.md deleted file mode 100644 index aa440b5145..0000000000 --- a/docs/examples/1.6.x/console-cli/examples/functions/download-deployment.md +++ /dev/null @@ -1,3 +0,0 @@ -appwrite functions downloadDeployment \ - --functionId \ - --deploymentId diff --git a/docs/examples/1.6.x/console-cli/examples/functions/get-specifications.md b/docs/examples/1.6.x/console-cli/examples/functions/get-specifications.md deleted file mode 100644 index 4e612280e7..0000000000 --- a/docs/examples/1.6.x/console-cli/examples/functions/get-specifications.md +++ /dev/null @@ -1 +0,0 @@ -appwrite functions getSpecifications diff --git a/docs/examples/1.6.x/console-cli/examples/messaging/create-push.md b/docs/examples/1.6.x/console-cli/examples/messaging/create-push.md index e187342503..18d8ec5aec 100644 --- a/docs/examples/1.6.x/console-cli/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/console-cli/examples/messaging/create-push.md @@ -1,7 +1,10 @@ appwrite messaging createPush \ --messageId \ - --title \ - --body <BODY> \ + + + + + diff --git a/docs/examples/1.6.x/console-cli/examples/messaging/update-push.md b/docs/examples/1.6.x/console-cli/examples/messaging/update-push.md index 70f215c935..1f4427cee7 100644 --- a/docs/examples/1.6.x/console-cli/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/console-cli/examples/messaging/update-push.md @@ -15,3 +15,6 @@ appwrite messaging updatePush \ + + + diff --git a/docs/examples/1.6.x/console-cli/examples/migrations/create-firebase-o-auth-migration.md b/docs/examples/1.6.x/console-cli/examples/migrations/create-firebase-o-auth-migration.md deleted file mode 100644 index 207becba03..0000000000 --- a/docs/examples/1.6.x/console-cli/examples/migrations/create-firebase-o-auth-migration.md +++ /dev/null @@ -1,3 +0,0 @@ -appwrite migrations createFirebaseOAuthMigration \ - --resources one two three \ - --projectId <PROJECT_ID> diff --git a/docs/examples/1.6.x/console-cli/examples/migrations/delete-firebase-auth.md b/docs/examples/1.6.x/console-cli/examples/migrations/delete-firebase-auth.md deleted file mode 100644 index d58abd9878..0000000000 --- a/docs/examples/1.6.x/console-cli/examples/migrations/delete-firebase-auth.md +++ /dev/null @@ -1 +0,0 @@ -appwrite migrations deleteFirebaseAuth diff --git a/docs/examples/1.6.x/console-cli/examples/migrations/get-firebase-report-o-auth.md b/docs/examples/1.6.x/console-cli/examples/migrations/get-firebase-report-o-auth.md deleted file mode 100644 index 0bdbf3e435..0000000000 --- a/docs/examples/1.6.x/console-cli/examples/migrations/get-firebase-report-o-auth.md +++ /dev/null @@ -1,3 +0,0 @@ -appwrite migrations getFirebaseReportOAuth \ - --resources one two three \ - --projectId <PROJECT_ID> diff --git a/docs/examples/1.6.x/console-cli/examples/migrations/list-firebase-projects.md b/docs/examples/1.6.x/console-cli/examples/migrations/list-firebase-projects.md deleted file mode 100644 index a0e59713eb..0000000000 --- a/docs/examples/1.6.x/console-cli/examples/migrations/list-firebase-projects.md +++ /dev/null @@ -1 +0,0 @@ -appwrite migrations listFirebaseProjects diff --git a/docs/examples/1.6.x/console-cli/examples/projects/update-memberships-privacy.md b/docs/examples/1.6.x/console-cli/examples/projects/update-memberships-privacy.md new file mode 100644 index 0000000000..6c811ccfce --- /dev/null +++ b/docs/examples/1.6.x/console-cli/examples/projects/update-memberships-privacy.md @@ -0,0 +1,5 @@ +appwrite projects updateMembershipsPrivacy \ + --projectId <PROJECT_ID> \ + --userName false \ + --userEmail false \ + --mfa false diff --git a/docs/examples/1.6.x/console-web/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/console-web/examples/databases/update-string-attribute.md index 0ac1497d00..f652c304eb 100644 --- a/docs/examples/1.6.x/console-web/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/console-web/examples/databases/update-string-attribute.md @@ -12,7 +12,7 @@ const result = await databases.updateStringAttribute( '', // key false, // required '<DEFAULT>', // default - null, // size (optional) + 1, // size (optional) '' // newKey (optional) ); diff --git a/docs/examples/1.6.x/console-web/examples/functions/download-deployment.md b/docs/examples/1.6.x/console-web/examples/functions/download-deployment.md deleted file mode 100644 index 8115c7e130..0000000000 --- a/docs/examples/1.6.x/console-web/examples/functions/download-deployment.md +++ /dev/null @@ -1,14 +0,0 @@ -import { Client, Functions } from "@appwrite.io/console"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const functions = new Functions(client); - -const result = functions.downloadDeployment( - '<FUNCTION_ID>', // functionId - '<DEPLOYMENT_ID>' // deploymentId -); - -console.log(result); diff --git a/docs/examples/1.6.x/console-web/examples/functions/get-specifications.md b/docs/examples/1.6.x/console-web/examples/functions/get-specifications.md deleted file mode 100644 index c5cb3fc043..0000000000 --- a/docs/examples/1.6.x/console-web/examples/functions/get-specifications.md +++ /dev/null @@ -1,11 +0,0 @@ -import { Client, Functions } from "@appwrite.io/console"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const functions = new Functions(client); - -const result = await functions.getSpecifications(); - -console.log(result); diff --git a/docs/examples/1.6.x/console-web/examples/messaging/create-push.md b/docs/examples/1.6.x/console-web/examples/messaging/create-push.md index fe8eac62ab..9a4fd4269a 100644 --- a/docs/examples/1.6.x/console-web/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/console-web/examples/messaging/create-push.md @@ -1,4 +1,4 @@ -import { Client, Messaging } from "@appwrite.io/console"; +import { Client, Messaging, MessagePriority } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint @@ -8,8 +8,8 @@ const messaging = new Messaging(client); const result = await messaging.createPush( '<MESSAGE_ID>', // messageId - '<TITLE>', // title - '<BODY>', // body + '<TITLE>', // title (optional) + '<BODY>', // body (optional) [], // topics (optional) [], // users (optional) [], // targets (optional) @@ -20,9 +20,12 @@ const result = await messaging.createPush( '<SOUND>', // sound (optional) '<COLOR>', // color (optional) '<TAG>', // tag (optional) - '<BADGE>', // badge (optional) + null, // badge (optional) false, // draft (optional) - '' // scheduledAt (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.Normal // priority (optional) ); console.log(result); diff --git a/docs/examples/1.6.x/console-web/examples/messaging/update-push.md b/docs/examples/1.6.x/console-web/examples/messaging/update-push.md index 9fbb230304..fa2220d3c6 100644 --- a/docs/examples/1.6.x/console-web/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/console-web/examples/messaging/update-push.md @@ -1,4 +1,4 @@ -import { Client, Messaging } from "@appwrite.io/console"; +import { Client, Messaging, MessagePriority } from "@appwrite.io/console"; const client = new Client() .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint @@ -22,7 +22,10 @@ const result = await messaging.updatePush( '<TAG>', // tag (optional) null, // badge (optional) false, // draft (optional) - '' // scheduledAt (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.Normal // priority (optional) ); console.log(result); diff --git a/docs/examples/1.6.x/console-web/examples/migrations/create-firebase-o-auth-migration.md b/docs/examples/1.6.x/console-web/examples/migrations/create-firebase-o-auth-migration.md deleted file mode 100644 index bf57d427e9..0000000000 --- a/docs/examples/1.6.x/console-web/examples/migrations/create-firebase-o-auth-migration.md +++ /dev/null @@ -1,14 +0,0 @@ -import { Client, Migrations } from "@appwrite.io/console"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const migrations = new Migrations(client); - -const result = await migrations.createFirebaseOAuthMigration( - [], // resources - '<PROJECT_ID>' // projectId -); - -console.log(result); diff --git a/docs/examples/1.6.x/console-web/examples/migrations/delete-firebase-auth.md b/docs/examples/1.6.x/console-web/examples/migrations/delete-firebase-auth.md deleted file mode 100644 index 8c7683b46a..0000000000 --- a/docs/examples/1.6.x/console-web/examples/migrations/delete-firebase-auth.md +++ /dev/null @@ -1,11 +0,0 @@ -import { Client, Migrations } from "@appwrite.io/console"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const migrations = new Migrations(client); - -const result = await migrations.deleteFirebaseAuth(); - -console.log(result); diff --git a/docs/examples/1.6.x/console-web/examples/migrations/get-firebase-report-o-auth.md b/docs/examples/1.6.x/console-web/examples/migrations/get-firebase-report-o-auth.md deleted file mode 100644 index 055ddfba7c..0000000000 --- a/docs/examples/1.6.x/console-web/examples/migrations/get-firebase-report-o-auth.md +++ /dev/null @@ -1,14 +0,0 @@ -import { Client, Migrations } from "@appwrite.io/console"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const migrations = new Migrations(client); - -const result = await migrations.getFirebaseReportOAuth( - [], // resources - '<PROJECT_ID>' // projectId -); - -console.log(result); diff --git a/docs/examples/1.6.x/console-web/examples/migrations/list-firebase-projects.md b/docs/examples/1.6.x/console-web/examples/migrations/list-firebase-projects.md deleted file mode 100644 index 833c05fe24..0000000000 --- a/docs/examples/1.6.x/console-web/examples/migrations/list-firebase-projects.md +++ /dev/null @@ -1,11 +0,0 @@ -import { Client, Migrations } from "@appwrite.io/console"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const migrations = new Migrations(client); - -const result = await migrations.listFirebaseProjects(); - -console.log(result); diff --git a/docs/examples/1.6.x/console-web/examples/projects/update-memberships-privacy.md b/docs/examples/1.6.x/console-web/examples/projects/update-memberships-privacy.md new file mode 100644 index 0000000000..2cde25faa5 --- /dev/null +++ b/docs/examples/1.6.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://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.6.x/server-dart/examples/account/update-mfa-challenge.md b/docs/examples/1.6.x/server-dart/examples/account/update-mfa-challenge.md index fd64c61cf9..2843d2f1b4 100644 --- a/docs/examples/1.6.x/server-dart/examples/account/update-mfa-challenge.md +++ b/docs/examples/1.6.x/server-dart/examples/account/update-mfa-challenge.md @@ -7,7 +7,7 @@ Client client = Client() Account account = Account(client); - result = await account.updateMfaChallenge( +Session result = await account.updateMfaChallenge( challengeId: '<CHALLENGE_ID>', otp: '<OTP>', ); diff --git a/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md index c2f3804c66..f9498aa36b 100644 --- a/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-dart/examples/databases/update-string-attribute.md @@ -13,6 +13,6 @@ AttributeString result = await databases.updateStringAttribute( key: '', xrequired: false, xdefault: '<DEFAULT>', - size: 0, // (optional) + size: 1, // (optional) newKey: '', // (optional) ); diff --git a/docs/examples/1.6.x/server-dart/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-dart/examples/functions/download-deployment.md deleted file mode 100644 index 981de76756..0000000000 --- a/docs/examples/1.6.x/server-dart/examples/functions/download-deployment.md +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:dart_appwrite/dart_appwrite.dart'; - -Client client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>') // Your project ID - .setKey('<YOUR_API_KEY>'); // Your secret API key - -Functions functions = Functions(client); - -UInt8List result = await functions.downloadDeployment( - functionId: '<FUNCTION_ID>', - deploymentId: '<DEPLOYMENT_ID>', -); diff --git a/docs/examples/1.6.x/server-dart/examples/functions/get-template.md b/docs/examples/1.6.x/server-dart/examples/functions/get-template.md deleted file mode 100644 index 881dac6782..0000000000 --- a/docs/examples/1.6.x/server-dart/examples/functions/get-template.md +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:dart_appwrite/dart_appwrite.dart'; - -Client client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -Functions functions = Functions(client); - -TemplateFunction result = await functions.getTemplate( - templateId: '<TEMPLATE_ID>', -); diff --git a/docs/examples/1.6.x/server-dart/examples/functions/list-templates.md b/docs/examples/1.6.x/server-dart/examples/functions/list-templates.md deleted file mode 100644 index 7bef5106ed..0000000000 --- a/docs/examples/1.6.x/server-dart/examples/functions/list-templates.md +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:dart_appwrite/dart_appwrite.dart'; - -Client client = Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -Functions functions = Functions(client); - -TemplateFunctionList result = await functions.listTemplates( - runtimes: [], // (optional) - useCases: [], // (optional) - limit: 1, // (optional) - offset: 0, // (optional) -); diff --git a/docs/examples/1.6.x/server-dart/examples/messaging/create-push.md b/docs/examples/1.6.x/server-dart/examples/messaging/create-push.md index c3c7d2ffc5..e496de9d27 100644 --- a/docs/examples/1.6.x/server-dart/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-dart/examples/messaging/create-push.md @@ -9,8 +9,8 @@ Messaging messaging = Messaging(client); Message result = await messaging.createPush( messageId: '<MESSAGE_ID>', - title: '<TITLE>', - body: '<BODY>', + title: '<TITLE>', // (optional) + body: '<BODY>', // (optional) topics: [], // (optional) users: [], // (optional) targets: [], // (optional) @@ -21,7 +21,10 @@ Message result = await messaging.createPush( sound: '<SOUND>', // (optional) color: '<COLOR>', // (optional) tag: '<TAG>', // (optional) - badge: '<BADGE>', // (optional) + badge: 0, // (optional) draft: false, // (optional) scheduledAt: '', // (optional) + contentAvailable: false, // (optional) + critical: false, // (optional) + priority: MessagePriority.normal, // (optional) ); diff --git a/docs/examples/1.6.x/server-dart/examples/messaging/update-push.md b/docs/examples/1.6.x/server-dart/examples/messaging/update-push.md index dcec9b243f..f5d75332e2 100644 --- a/docs/examples/1.6.x/server-dart/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-dart/examples/messaging/update-push.md @@ -24,4 +24,7 @@ Message result = await messaging.updatePush( badge: 0, // (optional) draft: false, // (optional) scheduledAt: '', // (optional) + contentAvailable: false, // (optional) + critical: false, // (optional) + priority: MessagePriority.normal, // (optional) ); diff --git a/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md index 6603c377cb..d57f8fd663 100644 --- a/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-deno/examples/databases/update-string-attribute.md @@ -13,6 +13,6 @@ const response = await databases.updateStringAttribute( '', // key false, // required '<DEFAULT>', // default - null, // size (optional) + 1, // size (optional) '' // newKey (optional) ); diff --git a/docs/examples/1.6.x/server-deno/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-deno/examples/functions/download-deployment.md deleted file mode 100644 index bb0a4e71b4..0000000000 --- a/docs/examples/1.6.x/server-deno/examples/functions/download-deployment.md +++ /dev/null @@ -1,13 +0,0 @@ -import { Client, Functions } from "https://deno.land/x/appwrite/mod.ts"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>') // Your project ID - .setKey('<YOUR_API_KEY>'); // Your secret API key - -const functions = new Functions(client); - -const result = functions.downloadDeployment( - '<FUNCTION_ID>', // functionId - '<DEPLOYMENT_ID>' // deploymentId -); diff --git a/docs/examples/1.6.x/server-deno/examples/functions/get-template.md b/docs/examples/1.6.x/server-deno/examples/functions/get-template.md deleted file mode 100644 index 7a58c95a34..0000000000 --- a/docs/examples/1.6.x/server-deno/examples/functions/get-template.md +++ /dev/null @@ -1,11 +0,0 @@ -import { Client, Functions } from "https://deno.land/x/appwrite/mod.ts"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const functions = new Functions(client); - -const response = await functions.getTemplate( - '<TEMPLATE_ID>' // templateId -); diff --git a/docs/examples/1.6.x/server-deno/examples/functions/list-templates.md b/docs/examples/1.6.x/server-deno/examples/functions/list-templates.md deleted file mode 100644 index 06203e404b..0000000000 --- a/docs/examples/1.6.x/server-deno/examples/functions/list-templates.md +++ /dev/null @@ -1,14 +0,0 @@ -import { Client, Functions } from "https://deno.land/x/appwrite/mod.ts"; - -const client = new Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const functions = new Functions(client); - -const response = await functions.listTemplates( - [], // runtimes (optional) - [], // useCases (optional) - 1, // limit (optional) - 0 // offset (optional) -); diff --git a/docs/examples/1.6.x/server-deno/examples/messaging/create-push.md b/docs/examples/1.6.x/server-deno/examples/messaging/create-push.md index 005cca1b77..7b41911918 100644 --- a/docs/examples/1.6.x/server-deno/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-deno/examples/messaging/create-push.md @@ -1,4 +1,4 @@ -import { Client, Messaging } from "https://deno.land/x/appwrite/mod.ts"; +import { Client, Messaging, MessagePriority } from "https://deno.land/x/appwrite/mod.ts"; const client = new Client() .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint @@ -9,8 +9,8 @@ const messaging = new Messaging(client); const response = await messaging.createPush( '<MESSAGE_ID>', // messageId - '<TITLE>', // title - '<BODY>', // body + '<TITLE>', // title (optional) + '<BODY>', // body (optional) [], // topics (optional) [], // users (optional) [], // targets (optional) @@ -21,7 +21,10 @@ const response = await messaging.createPush( '<SOUND>', // sound (optional) '<COLOR>', // color (optional) '<TAG>', // tag (optional) - '<BADGE>', // badge (optional) + null, // badge (optional) false, // draft (optional) - '' // scheduledAt (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.Normal // priority (optional) ); diff --git a/docs/examples/1.6.x/server-deno/examples/messaging/update-push.md b/docs/examples/1.6.x/server-deno/examples/messaging/update-push.md index 9c66ab6ab7..11437fabe1 100644 --- a/docs/examples/1.6.x/server-deno/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-deno/examples/messaging/update-push.md @@ -1,4 +1,4 @@ -import { Client, Messaging } from "https://deno.land/x/appwrite/mod.ts"; +import { Client, Messaging, MessagePriority } from "https://deno.land/x/appwrite/mod.ts"; const client = new Client() .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint @@ -23,5 +23,8 @@ const response = await messaging.updatePush( '<TAG>', // tag (optional) null, // badge (optional) false, // draft (optional) - '' // scheduledAt (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.Normal // priority (optional) ); diff --git a/docs/examples/1.6.x/server-dotnet/examples/account/update-mfa-challenge.md b/docs/examples/1.6.x/server-dotnet/examples/account/update-mfa-challenge.md index edf863a36e..ec32f8c900 100644 --- a/docs/examples/1.6.x/server-dotnet/examples/account/update-mfa-challenge.md +++ b/docs/examples/1.6.x/server-dotnet/examples/account/update-mfa-challenge.md @@ -9,7 +9,7 @@ Client client = new Client() Account account = new Account(client); - result = await account.UpdateMfaChallenge( +Session result = await account.UpdateMfaChallenge( challengeId: "<CHALLENGE_ID>", otp: "<OTP>" ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md index e915d23f51..a180815a50 100644 --- a/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-dotnet/examples/databases/update-string-attribute.md @@ -15,6 +15,6 @@ AttributeString result = await databases.UpdateStringAttribute( key: "", required: false, default: "<DEFAULT>", - size: 0, // optional + size: 1, // optional newKey: "" // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-dotnet/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-dotnet/examples/functions/download-deployment.md deleted file mode 100644 index 83f56a8e14..0000000000 --- a/docs/examples/1.6.x/server-dotnet/examples/functions/download-deployment.md +++ /dev/null @@ -1,15 +0,0 @@ -using Appwrite; -using Appwrite.Models; -using Appwrite.Services; - -Client client = new Client() - .SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .SetProject("<YOUR_PROJECT_ID>") // Your project ID - .SetKey("<YOUR_API_KEY>"); // Your secret API key - -Functions functions = new Functions(client); - -byte[] result = await functions.DownloadDeployment( - functionId: "<FUNCTION_ID>", - deploymentId: "<DEPLOYMENT_ID>" -); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-dotnet/examples/functions/get-template.md b/docs/examples/1.6.x/server-dotnet/examples/functions/get-template.md deleted file mode 100644 index f57d61a024..0000000000 --- a/docs/examples/1.6.x/server-dotnet/examples/functions/get-template.md +++ /dev/null @@ -1,13 +0,0 @@ -using Appwrite; -using Appwrite.Models; -using Appwrite.Services; - -Client client = new Client() - .SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .SetProject("<YOUR_PROJECT_ID>"); // Your project ID - -Functions functions = new Functions(client); - -TemplateFunction result = await functions.GetTemplate( - templateId: "<TEMPLATE_ID>" -); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-dotnet/examples/functions/list-templates.md b/docs/examples/1.6.x/server-dotnet/examples/functions/list-templates.md deleted file mode 100644 index f76bd5fa9c..0000000000 --- a/docs/examples/1.6.x/server-dotnet/examples/functions/list-templates.md +++ /dev/null @@ -1,16 +0,0 @@ -using Appwrite; -using Appwrite.Models; -using Appwrite.Services; - -Client client = new Client() - .SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .SetProject("<YOUR_PROJECT_ID>"); // Your project ID - -Functions functions = new Functions(client); - -TemplateFunctionList result = await functions.ListTemplates( - runtimes: new List<string>(), // optional - useCases: new List<string>(), // optional - limit: 1, // optional - offset: 0 // optional -); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-dotnet/examples/messaging/create-push.md b/docs/examples/1.6.x/server-dotnet/examples/messaging/create-push.md index f83a0ed8df..588781b3a1 100644 --- a/docs/examples/1.6.x/server-dotnet/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-dotnet/examples/messaging/create-push.md @@ -1,4 +1,5 @@ using Appwrite; +using Appwrite.Enums; using Appwrite.Models; using Appwrite.Services; @@ -11,8 +12,8 @@ Messaging messaging = new Messaging(client); Message result = await messaging.CreatePush( messageId: "<MESSAGE_ID>", - title: "<TITLE>", - body: "<BODY>", + title: "<TITLE>", // optional + body: "<BODY>", // optional topics: new List<string>(), // optional users: new List<string>(), // optional targets: new List<string>(), // optional @@ -23,7 +24,10 @@ Message result = await messaging.CreatePush( sound: "<SOUND>", // optional color: "<COLOR>", // optional tag: "<TAG>", // optional - badge: "<BADGE>", // optional + badge: 0, // optional draft: false, // optional - scheduledAt: "" // optional + scheduledAt: "", // optional + contentAvailable: false, // optional + critical: false, // optional + priority: MessagePriority.Normal // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-dotnet/examples/messaging/update-push.md b/docs/examples/1.6.x/server-dotnet/examples/messaging/update-push.md index 0de09d570a..2b48d1827d 100644 --- a/docs/examples/1.6.x/server-dotnet/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-dotnet/examples/messaging/update-push.md @@ -1,4 +1,5 @@ using Appwrite; +using Appwrite.Enums; using Appwrite.Models; using Appwrite.Services; @@ -25,5 +26,8 @@ Message result = await messaging.UpdatePush( tag: "<TAG>", // optional badge: 0, // optional draft: false, // optional - scheduledAt: "" // optional + scheduledAt: "", // optional + contentAvailable: false, // optional + critical: false, // optional + priority: MessagePriority.Normal // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md index d662060f09..f3e6addb07 100644 --- a/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-go/examples/databases/update-string-attribute.md @@ -20,7 +20,7 @@ func main() { "", false, "<DEFAULT>", - databases.WithUpdateStringAttributeSize(0), + databases.WithUpdateStringAttributeSize(1), databases.WithUpdateStringAttributeNewKey(""), ) diff --git a/docs/examples/1.6.x/server-go/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-go/examples/functions/download-deployment.md deleted file mode 100644 index 37d2149541..0000000000 --- a/docs/examples/1.6.x/server-go/examples/functions/download-deployment.md +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "fmt" - "github.com/appwrite/sdk-for-go/client" - "github.com/appwrite/sdk-for-go/functions" -) - -func main() { - client := client.NewClient() - - client.SetEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - client.SetProject("") // Your project ID - client.SetKey("") // Your secret API key - - service := functions.NewFunctions(client) - response, error := service.DownloadDeployment( - "<FUNCTION_ID>", - "<DEPLOYMENT_ID>", - ) - - if error != nil { - panic(error) - } - - fmt.Println(response) -} diff --git a/docs/examples/1.6.x/server-go/examples/functions/get-template.md b/docs/examples/1.6.x/server-go/examples/functions/get-template.md deleted file mode 100644 index fe4e1debb9..0000000000 --- a/docs/examples/1.6.x/server-go/examples/functions/get-template.md +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "fmt" - "github.com/appwrite/sdk-for-go/client" - "github.com/appwrite/sdk-for-go/functions" -) - -func main() { - client := client.NewClient() - - client.SetEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - client.SetProject("<YOUR_PROJECT_ID>") // Your project ID - - service := functions.NewFunctions(client) - response, error := service.GetTemplate( - "<TEMPLATE_ID>", - ) - - if error != nil { - panic(error) - } - - fmt.Println(response) -} diff --git a/docs/examples/1.6.x/server-go/examples/functions/list-templates.md b/docs/examples/1.6.x/server-go/examples/functions/list-templates.md deleted file mode 100644 index 19edf6d360..0000000000 --- a/docs/examples/1.6.x/server-go/examples/functions/list-templates.md +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "fmt" - "github.com/appwrite/sdk-for-go/client" - "github.com/appwrite/sdk-for-go/functions" -) - -func main() { - client := client.NewClient() - - client.SetEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - client.SetProject("<YOUR_PROJECT_ID>") // Your project ID - - service := functions.NewFunctions(client) - response, error := service.ListTemplates( - functions.WithListTemplatesRuntimes([]interface{}{}), - functions.WithListTemplatesUseCases([]interface{}{}), - functions.WithListTemplatesLimit(1), - functions.WithListTemplatesOffset(0), - ) - - if error != nil { - panic(error) - } - - fmt.Println(response) -} diff --git a/docs/examples/1.6.x/server-go/examples/messaging/create-push.md b/docs/examples/1.6.x/server-go/examples/messaging/create-push.md index 090e0cbca2..b40037472f 100644 --- a/docs/examples/1.6.x/server-go/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-go/examples/messaging/create-push.md @@ -16,8 +16,8 @@ func main() { service := messaging.NewMessaging(client) response, error := service.CreatePush( "<MESSAGE_ID>", - "<TITLE>", - "<BODY>", + messaging.WithCreatePushTitle("<TITLE>"), + messaging.WithCreatePushBody("<BODY>"), messaging.WithCreatePushTopics([]interface{}{}), messaging.WithCreatePushUsers([]interface{}{}), messaging.WithCreatePushTargets([]interface{}{}), @@ -28,9 +28,12 @@ func main() { messaging.WithCreatePushSound("<SOUND>"), messaging.WithCreatePushColor("<COLOR>"), messaging.WithCreatePushTag("<TAG>"), - messaging.WithCreatePushBadge("<BADGE>"), + messaging.WithCreatePushBadge(0), messaging.WithCreatePushDraft(false), messaging.WithCreatePushScheduledAt(""), + messaging.WithCreatePushContentAvailable(false), + messaging.WithCreatePushCritical(false), + messaging.WithCreatePushPriority("normal"), ) if error != nil { diff --git a/docs/examples/1.6.x/server-go/examples/messaging/update-push.md b/docs/examples/1.6.x/server-go/examples/messaging/update-push.md index af1b6095cd..d1b47256c0 100644 --- a/docs/examples/1.6.x/server-go/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-go/examples/messaging/update-push.md @@ -31,6 +31,9 @@ func main() { messaging.WithUpdatePushBadge(0), messaging.WithUpdatePushDraft(false), messaging.WithUpdatePushScheduledAt(""), + messaging.WithUpdatePushContentAvailable(false), + messaging.WithUpdatePushCritical(false), + messaging.WithUpdatePushPriority("normal"), ) if error != nil { diff --git a/docs/examples/1.6.x/server-graphql/examples/account/create.md b/docs/examples/1.6.x/server-graphql/examples/account/create.md index 3f8e3c3cf7..0d39394a3d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/create.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/create.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/get.md b/docs/examples/1.6.x/server-graphql/examples/account/get.md index e4db8f0e41..f4f07c187f 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/get.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/get.md @@ -28,6 +28,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-email.md b/docs/examples/1.6.x/server-graphql/examples/account/update-email.md index b207bad4bb..c879e24a43 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-email.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-email.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md b/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md index d2cd3d6ae5..787c2e0860 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-m-f-a.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md b/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md index c74062c7d4..9cfe9150be 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-authenticator.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-challenge.md b/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-challenge.md index 8237431bcf..0bcec2157f 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-challenge.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-mfa-challenge.md @@ -3,6 +3,34 @@ mutation { challengeId: "<CHALLENGE_ID>", otp: "<OTP>" ) { - status + _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 } } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-name.md b/docs/examples/1.6.x/server-graphql/examples/account/update-name.md index 850b5760a0..8ba2c99d9c 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-name.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-name.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-password.md b/docs/examples/1.6.x/server-graphql/examples/account/update-password.md index 5904da0842..f3619a10d2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-password.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-password.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md b/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md index 408a203300..adecb71168 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-phone.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md b/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md index 40db7b43db..57280247e4 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-prefs.md @@ -30,6 +30,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/account/update-status.md b/docs/examples/1.6.x/server-graphql/examples/account/update-status.md index aca8c098e7..c17f556842 100644 --- a/docs/examples/1.6.x/server-graphql/examples/account/update-status.md +++ b/docs/examples/1.6.x/server-graphql/examples/account/update-status.md @@ -28,6 +28,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md index 6e969a587e..aa0bfa832e 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-boolean-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt default } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md index 05175cc1e7..51eb51f410 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-collection.md @@ -23,6 +23,8 @@ mutation { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md index fcd5cb37a2..47601df0d8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-datetime-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md index 1f23a23ba7..e5845ccd47 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-email-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md index 410a7983b4..d13c080e4a 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-enum-attribute.md @@ -14,6 +14,8 @@ mutation { error required array + _createdAt + _updatedAt elements format default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md index ae6f9f72d6..2a270c3aff 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-float-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md index efc92a798c..2875a9b4b7 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-index.md @@ -13,5 +13,7 @@ mutation { error attributes orders + _createdAt + _updatedAt } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md index 1dc43f6b0d..8c79706817 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-integer-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md index b2fd7215a0..0f4ad9e139 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-ip-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md index ddca20b83a..f66b87d6af 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-relationship-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt relatedCollection relationType twoWay diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md index 3c290712e9..62d97d6962 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-string-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt size default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md index d2a39756c9..89ad873e52 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/create-url-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md b/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md index f76b71b6ba..ed27286b0d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/get-collection.md @@ -19,6 +19,8 @@ query { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md b/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md index de3c44ebe0..29de7a76f8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/get-index.md @@ -10,5 +10,7 @@ query { error attributes orders + _createdAt + _updatedAt } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md b/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md index b821b6c4cf..8dafbf7042 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/list-collections.md @@ -22,6 +22,8 @@ query { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md b/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md index e1c11b6c03..3cb67c6451 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/list-indexes.md @@ -12,6 +12,8 @@ query { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md index e92b41a14e..d508e62139 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-boolean-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt default } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md index fc78bb8efc..e918c058b8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-collection.md @@ -23,6 +23,8 @@ mutation { error attributes orders + _createdAt + _updatedAt } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md index 46d9bbb728..a21b910edc 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-datetime-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md index e05d365162..6c83d80e16 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-email-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md index 619cbf817c..378e32f9b8 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-enum-attribute.md @@ -14,6 +14,8 @@ mutation { error required array + _createdAt + _updatedAt elements format default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md index 7641745a35..c5c7afca44 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-float-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md index 11b7a66014..e38ccaa88c 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-integer-attribute.md @@ -15,6 +15,8 @@ mutation { error required array + _createdAt + _updatedAt min max default diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md index 649fa881b5..7a26224200 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-ip-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md index 88ba2f9636..6694540d93 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-relationship-attribute.md @@ -12,6 +12,8 @@ mutation { error required array + _createdAt + _updatedAt relatedCollection relationType twoWay diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md index 4d88462efb..afafb307f5 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-string-attribute.md @@ -5,7 +5,7 @@ mutation { key: "", required: false, default: "<DEFAULT>", - size: 0, + size: 1, newKey: "" ) { key @@ -14,6 +14,8 @@ mutation { error required array + _createdAt + _updatedAt size default } diff --git a/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md b/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md index 06838a9ed4..f9f14a04f6 100644 --- a/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md +++ b/docs/examples/1.6.x/server-graphql/examples/databases/update-url-attribute.md @@ -13,6 +13,8 @@ mutation { error required array + _createdAt + _updatedAt format default } diff --git a/docs/examples/1.6.x/server-graphql/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-graphql/examples/functions/download-deployment.md deleted file mode 100644 index f791338765..0000000000 --- a/docs/examples/1.6.x/server-graphql/examples/functions/download-deployment.md +++ /dev/null @@ -1,8 +0,0 @@ -query { - functionsDownloadDeployment( - functionId: "<FUNCTION_ID>", - deploymentId: "<DEPLOYMENT_ID>" - ) { - status - } -} diff --git a/docs/examples/1.6.x/server-graphql/examples/functions/get-template.md b/docs/examples/1.6.x/server-graphql/examples/functions/get-template.md deleted file mode 100644 index 44a466de27..0000000000 --- a/docs/examples/1.6.x/server-graphql/examples/functions/get-template.md +++ /dev/null @@ -1,35 +0,0 @@ -query { - functionsGetTemplate( - templateId: "<TEMPLATE_ID>" - ) { - icon - id - name - tagline - permissions - events - cron - timeout - useCases - runtimes { - name - commands - entrypoint - providerRootDirectory - } - instructions - vcsProvider - providerRepositoryId - providerOwner - providerVersion - variables { - name - description - value - placeholder - required - type - } - scopes - } -} diff --git a/docs/examples/1.6.x/server-graphql/examples/functions/list-templates.md b/docs/examples/1.6.x/server-graphql/examples/functions/list-templates.md deleted file mode 100644 index cb289ddabb..0000000000 --- a/docs/examples/1.6.x/server-graphql/examples/functions/list-templates.md +++ /dev/null @@ -1,41 +0,0 @@ -query { - functionsListTemplates( - runtimes: [], - useCases: [], - limit: 1, - offset: 0 - ) { - total - templates { - icon - id - name - tagline - permissions - events - cron - timeout - useCases - runtimes { - name - commands - entrypoint - providerRootDirectory - } - instructions - vcsProvider - providerRepositoryId - providerOwner - providerVersion - variables { - name - description - value - placeholder - required - type - } - scopes - } - } -} diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/create-push.md b/docs/examples/1.6.x/server-graphql/examples/messaging/create-push.md index 3084c97635..92264d1b67 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/create-push.md @@ -13,9 +13,12 @@ mutation { sound: "<SOUND>", color: "<COLOR>", tag: "<TAG>", - badge: "<BADGE>", + badge: 0, draft: false, - scheduledAt: "" + scheduledAt: "", + contentAvailable: false, + critical: false, + priority: "normal" ) { _id _createdAt diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md b/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md index b2712ebb48..bab53612b7 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/create-subscriber.md @@ -17,6 +17,7 @@ mutation { providerId providerType identifier + expired } userId userName diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md b/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md index 54096dd70a..2e1672d010 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/get-subscriber.md @@ -16,6 +16,7 @@ query { providerId providerType identifier + expired } userId userName diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md b/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md index 5c48ae34bb..a5a4f91e56 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/list-subscribers.md @@ -19,6 +19,7 @@ query { providerId providerType identifier + expired } userId userName diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md b/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md index 8e356dce5f..aa82276de2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/list-targets.md @@ -13,6 +13,7 @@ query { providerId providerType identifier + expired } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/messaging/update-push.md b/docs/examples/1.6.x/server-graphql/examples/messaging/update-push.md index 9039792573..8ee2f57610 100644 --- a/docs/examples/1.6.x/server-graphql/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-graphql/examples/messaging/update-push.md @@ -15,7 +15,10 @@ mutation { tag: "<TAG>", badge: 0, draft: false, - scheduledAt: "" + scheduledAt: "", + contentAvailable: false, + critical: false, + priority: "normal" ) { _id _createdAt diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md index 464dc754c9..7f99622e52 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-argon2user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md index 4d4bb09194..26659176eb 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-bcrypt-user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md index e8e833e6de..7e642b8233 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-m-d5user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md index 53960e7890..4c06b007a2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-p-h-pass-user.md @@ -33,6 +33,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md index 17e287f8b3..f99da2752d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-s-h-a-user.md @@ -34,6 +34,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md index 6d51fb29ba..624ffcdd38 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-modified-user.md @@ -36,6 +36,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md index 0d4bac1db8..68a5f4c75f 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-scrypt-user.md @@ -38,6 +38,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create-target.md b/docs/examples/1.6.x/server-graphql/examples/users/create-target.md index a3a0696dec..7068c21aba 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create-target.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create-target.md @@ -15,5 +15,6 @@ mutation { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/create.md b/docs/examples/1.6.x/server-graphql/examples/users/create.md index 826a5168ef..465da80432 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/create.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/create.md @@ -34,6 +34,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md b/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md index 227c340c68..43f73404f0 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/delete-mfa-authenticator.md @@ -3,35 +3,6 @@ mutation { userId: "<USER_ID>", type: "totp" ) { - _id - _createdAt - _updatedAt - name - password - hash - hashOptions - registration status - labels - passwordUpdate - email - phone - emailVerification - phoneVerification - mfa - prefs { - data - } - targets { - _id - _createdAt - _updatedAt - name - userId - providerId - providerType - identifier - } - accessedAt } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/get-target.md b/docs/examples/1.6.x/server-graphql/examples/users/get-target.md index e4ba1a04a1..c84f947898 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/get-target.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/get-target.md @@ -11,5 +11,6 @@ query { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/get.md b/docs/examples/1.6.x/server-graphql/examples/users/get.md index f94a5818ed..9d0be685d9 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/get.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/get.md @@ -30,6 +30,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md b/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md index 05e796f167..408fd96f80 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/list-targets.md @@ -13,6 +13,7 @@ query { providerId providerType identifier + expired } } } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/list.md b/docs/examples/1.6.x/server-graphql/examples/users/list.md index e2326dd1a2..a90121adf2 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/list.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/list.md @@ -33,6 +33,7 @@ query { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md b/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md index 6bb2781854..cda7278ac0 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-email-verification.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-email.md b/docs/examples/1.6.x/server-graphql/examples/users/update-email.md index 046937ac04..408a74972b 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-email.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-email.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md b/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md index 93da33d805..cb3c5b6483 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-labels.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md b/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md index 9219aa1aea..ac09ea19a4 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-mfa.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-name.md b/docs/examples/1.6.x/server-graphql/examples/users/update-name.md index 01a53ce479..ec7e3dc27c 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-name.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-name.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-password.md b/docs/examples/1.6.x/server-graphql/examples/users/update-password.md index c95637c4ce..95ef74c83d 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-password.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-password.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md b/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md index 58343ae365..c6afa54ba4 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-phone-verification.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md b/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md index dbcb076c65..d3fc7d5f37 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-phone.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-status.md b/docs/examples/1.6.x/server-graphql/examples/users/update-status.md index ad05bc75ff..2499c1c258 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-status.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-status.md @@ -31,6 +31,7 @@ mutation { providerId providerType identifier + expired } accessedAt } diff --git a/docs/examples/1.6.x/server-graphql/examples/users/update-target.md b/docs/examples/1.6.x/server-graphql/examples/users/update-target.md index fe3444ede7..1f7cc1147a 100644 --- a/docs/examples/1.6.x/server-graphql/examples/users/update-target.md +++ b/docs/examples/1.6.x/server-graphql/examples/users/update-target.md @@ -14,5 +14,6 @@ mutation { providerId providerType identifier + expired } } diff --git a/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md b/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md index 75be9e01f8..2d69006181 100644 --- a/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-kotlin/java/databases/update-string-attribute.md @@ -15,7 +15,7 @@ databases.updateStringAttribute( "", // key false, // required "<DEFAULT>", // default - 0, // size (optional) + 1, // size (optional) "", // newKey (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { diff --git a/docs/examples/1.6.x/server-kotlin/java/functions/download-deployment.md b/docs/examples/1.6.x/server-kotlin/java/functions/download-deployment.md deleted file mode 100644 index 77e4809379..0000000000 --- a/docs/examples/1.6.x/server-kotlin/java/functions/download-deployment.md +++ /dev/null @@ -1,24 +0,0 @@ -import io.appwrite.Client; -import io.appwrite.coroutines.CoroutineCallback; -import io.appwrite.services.Functions; - -Client client = new Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("<YOUR_PROJECT_ID>") // Your project ID - .setKey("<YOUR_API_KEY>"); // Your secret API key - -Functions functions = new Functions(client); - -functions.downloadDeployment( - "<FUNCTION_ID>", // functionId - "<DEPLOYMENT_ID>", // deploymentId - new CoroutineCallback<>((result, error) -> { - if (error != null) { - error.printStackTrace(); - return; - } - - System.out.println(result); - }) -); - diff --git a/docs/examples/1.6.x/server-kotlin/java/functions/get-template.md b/docs/examples/1.6.x/server-kotlin/java/functions/get-template.md deleted file mode 100644 index 1521fa47c1..0000000000 --- a/docs/examples/1.6.x/server-kotlin/java/functions/get-template.md +++ /dev/null @@ -1,22 +0,0 @@ -import io.appwrite.Client; -import io.appwrite.coroutines.CoroutineCallback; -import io.appwrite.services.Functions; - -Client client = new Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("<YOUR_PROJECT_ID>"); // Your project ID - -Functions functions = new Functions(client); - -functions.getTemplate( - "<TEMPLATE_ID>", // templateId - new CoroutineCallback<>((result, error) -> { - if (error != null) { - error.printStackTrace(); - return; - } - - System.out.println(result); - }) -); - diff --git a/docs/examples/1.6.x/server-kotlin/java/functions/list-templates.md b/docs/examples/1.6.x/server-kotlin/java/functions/list-templates.md deleted file mode 100644 index e88e19124f..0000000000 --- a/docs/examples/1.6.x/server-kotlin/java/functions/list-templates.md +++ /dev/null @@ -1,25 +0,0 @@ -import io.appwrite.Client; -import io.appwrite.coroutines.CoroutineCallback; -import io.appwrite.services.Functions; - -Client client = new Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("<YOUR_PROJECT_ID>"); // Your project ID - -Functions functions = new Functions(client); - -functions.listTemplates( - listOf(), // runtimes (optional) - listOf(), // useCases (optional) - 1, // limit (optional) - 0, // offset (optional) - new CoroutineCallback<>((result, error) -> { - if (error != null) { - error.printStackTrace(); - return; - } - - System.out.println(result); - }) -); - diff --git a/docs/examples/1.6.x/server-kotlin/java/messaging/create-push.md b/docs/examples/1.6.x/server-kotlin/java/messaging/create-push.md index 934f1faaa8..56c7a60795 100644 --- a/docs/examples/1.6.x/server-kotlin/java/messaging/create-push.md +++ b/docs/examples/1.6.x/server-kotlin/java/messaging/create-push.md @@ -11,8 +11,8 @@ Messaging messaging = new Messaging(client); messaging.createPush( "<MESSAGE_ID>", // messageId - "<TITLE>", // title - "<BODY>", // body + "<TITLE>", // title (optional) + "<BODY>", // body (optional) listOf(), // topics (optional) listOf(), // users (optional) listOf(), // targets (optional) @@ -23,9 +23,12 @@ messaging.createPush( "<SOUND>", // sound (optional) "<COLOR>", // color (optional) "<TAG>", // tag (optional) - "<BADGE>", // badge (optional) + 0, // badge (optional) false, // draft (optional) "", // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.NORMAL, // priority (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.6.x/server-kotlin/java/messaging/update-push.md b/docs/examples/1.6.x/server-kotlin/java/messaging/update-push.md index ef04203c37..bb8c3c8c2e 100644 --- a/docs/examples/1.6.x/server-kotlin/java/messaging/update-push.md +++ b/docs/examples/1.6.x/server-kotlin/java/messaging/update-push.md @@ -26,6 +26,9 @@ messaging.updatePush( 0, // badge (optional) false, // draft (optional) "", // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.NORMAL, // priority (optional) new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md b/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md index a37d4566ee..32e17beb9c 100644 --- a/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-kotlin/kotlin/databases/update-string-attribute.md @@ -15,6 +15,6 @@ val response = databases.updateStringAttribute( key = "", required = false, default = "<DEFAULT>", - size = 0, // optional + size = 1, // optional newKey = "" // optional ) diff --git a/docs/examples/1.6.x/server-kotlin/kotlin/functions/download-deployment.md b/docs/examples/1.6.x/server-kotlin/kotlin/functions/download-deployment.md deleted file mode 100644 index 0ae36b314f..0000000000 --- a/docs/examples/1.6.x/server-kotlin/kotlin/functions/download-deployment.md +++ /dev/null @@ -1,15 +0,0 @@ -import io.appwrite.Client -import io.appwrite.coroutines.CoroutineCallback -import io.appwrite.services.Functions - -val client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("<YOUR_PROJECT_ID>") // Your project ID - .setKey("<YOUR_API_KEY>") // Your secret API key - -val functions = Functions(client) - -val result = functions.downloadDeployment( - functionId = "<FUNCTION_ID>", - deploymentId = "<DEPLOYMENT_ID>" -) diff --git a/docs/examples/1.6.x/server-kotlin/kotlin/functions/get-template.md b/docs/examples/1.6.x/server-kotlin/kotlin/functions/get-template.md deleted file mode 100644 index 53d838f7e6..0000000000 --- a/docs/examples/1.6.x/server-kotlin/kotlin/functions/get-template.md +++ /dev/null @@ -1,13 +0,0 @@ -import io.appwrite.Client -import io.appwrite.coroutines.CoroutineCallback -import io.appwrite.services.Functions - -val client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("<YOUR_PROJECT_ID>") // Your project ID - -val functions = Functions(client) - -val response = functions.getTemplate( - templateId = "<TEMPLATE_ID>" -) diff --git a/docs/examples/1.6.x/server-kotlin/kotlin/functions/list-templates.md b/docs/examples/1.6.x/server-kotlin/kotlin/functions/list-templates.md deleted file mode 100644 index 37dc89ce89..0000000000 --- a/docs/examples/1.6.x/server-kotlin/kotlin/functions/list-templates.md +++ /dev/null @@ -1,16 +0,0 @@ -import io.appwrite.Client -import io.appwrite.coroutines.CoroutineCallback -import io.appwrite.services.Functions - -val client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("<YOUR_PROJECT_ID>") // Your project ID - -val functions = Functions(client) - -val response = functions.listTemplates( - runtimes = listOf(), // optional - useCases = listOf(), // optional - limit = 1, // optional - offset = 0 // optional -) diff --git a/docs/examples/1.6.x/server-kotlin/kotlin/messaging/create-push.md b/docs/examples/1.6.x/server-kotlin/kotlin/messaging/create-push.md index 6a95f63992..f92a49d627 100644 --- a/docs/examples/1.6.x/server-kotlin/kotlin/messaging/create-push.md +++ b/docs/examples/1.6.x/server-kotlin/kotlin/messaging/create-push.md @@ -11,8 +11,8 @@ val messaging = Messaging(client) val response = messaging.createPush( messageId = "<MESSAGE_ID>", - title = "<TITLE>", - body = "<BODY>", + title = "<TITLE>", // optional + body = "<BODY>", // optional topics = listOf(), // optional users = listOf(), // optional targets = listOf(), // optional @@ -23,7 +23,10 @@ val response = messaging.createPush( sound = "<SOUND>", // optional color = "<COLOR>", // optional tag = "<TAG>", // optional - badge = "<BADGE>", // optional + badge = 0, // optional draft = false, // optional - scheduledAt = "" // optional + scheduledAt = "", // optional + contentAvailable = false, // optional + critical = false, // optional + priority = "normal" // optional ) diff --git a/docs/examples/1.6.x/server-kotlin/kotlin/messaging/update-push.md b/docs/examples/1.6.x/server-kotlin/kotlin/messaging/update-push.md index d91694e1bc..0ba72c461c 100644 --- a/docs/examples/1.6.x/server-kotlin/kotlin/messaging/update-push.md +++ b/docs/examples/1.6.x/server-kotlin/kotlin/messaging/update-push.md @@ -25,5 +25,8 @@ val response = messaging.updatePush( tag = "<TAG>", // optional badge = 0, // optional draft = false, // optional - scheduledAt = "" // optional + scheduledAt = "", // optional + contentAvailable = false, // optional + critical = false, // optional + priority = "normal" // optional ) diff --git a/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md index f379fdc0cf..6aecbb591e 100644 --- a/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-nodejs/examples/databases/update-string-attribute.md @@ -13,6 +13,6 @@ const result = await databases.updateStringAttribute( '', // key false, // required '<DEFAULT>', // default - null, // size (optional) + 1, // size (optional) '' // newKey (optional) ); diff --git a/docs/examples/1.6.x/server-nodejs/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-nodejs/examples/functions/download-deployment.md deleted file mode 100644 index e0962db0ed..0000000000 --- a/docs/examples/1.6.x/server-nodejs/examples/functions/download-deployment.md +++ /dev/null @@ -1,13 +0,0 @@ -const sdk = require('node-appwrite'); - -const client = new sdk.Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>') // Your project ID - .setKey('<YOUR_API_KEY>'); // Your secret API key - -const functions = new sdk.Functions(client); - -const result = await functions.downloadDeployment( - '<FUNCTION_ID>', // functionId - '<DEPLOYMENT_ID>' // deploymentId -); diff --git a/docs/examples/1.6.x/server-nodejs/examples/functions/get-template.md b/docs/examples/1.6.x/server-nodejs/examples/functions/get-template.md deleted file mode 100644 index 36195db7f3..0000000000 --- a/docs/examples/1.6.x/server-nodejs/examples/functions/get-template.md +++ /dev/null @@ -1,11 +0,0 @@ -const sdk = require('node-appwrite'); - -const client = new sdk.Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const functions = new sdk.Functions(client); - -const result = await functions.getTemplate( - '<TEMPLATE_ID>' // templateId -); diff --git a/docs/examples/1.6.x/server-nodejs/examples/functions/list-templates.md b/docs/examples/1.6.x/server-nodejs/examples/functions/list-templates.md deleted file mode 100644 index 6f896cac97..0000000000 --- a/docs/examples/1.6.x/server-nodejs/examples/functions/list-templates.md +++ /dev/null @@ -1,14 +0,0 @@ -const sdk = require('node-appwrite'); - -const client = new sdk.Client() - .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - .setProject('<YOUR_PROJECT_ID>'); // Your project ID - -const functions = new sdk.Functions(client); - -const result = await functions.listTemplates( - [], // runtimes (optional) - [], // useCases (optional) - 1, // limit (optional) - 0 // offset (optional) -); diff --git a/docs/examples/1.6.x/server-nodejs/examples/messaging/create-push.md b/docs/examples/1.6.x/server-nodejs/examples/messaging/create-push.md index 54103e11f7..bb98538748 100644 --- a/docs/examples/1.6.x/server-nodejs/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-nodejs/examples/messaging/create-push.md @@ -9,8 +9,8 @@ const messaging = new sdk.Messaging(client); const result = await messaging.createPush( '<MESSAGE_ID>', // messageId - '<TITLE>', // title - '<BODY>', // body + '<TITLE>', // title (optional) + '<BODY>', // body (optional) [], // topics (optional) [], // users (optional) [], // targets (optional) @@ -21,7 +21,10 @@ const result = await messaging.createPush( '<SOUND>', // sound (optional) '<COLOR>', // color (optional) '<TAG>', // tag (optional) - '<BADGE>', // badge (optional) + null, // badge (optional) false, // draft (optional) - '' // scheduledAt (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + sdk.MessagePriority.Normal // priority (optional) ); diff --git a/docs/examples/1.6.x/server-nodejs/examples/messaging/update-push.md b/docs/examples/1.6.x/server-nodejs/examples/messaging/update-push.md index ec87ecf7cf..700c3a99de 100644 --- a/docs/examples/1.6.x/server-nodejs/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-nodejs/examples/messaging/update-push.md @@ -23,5 +23,8 @@ const result = await messaging.updatePush( '<TAG>', // tag (optional) null, // badge (optional) false, // draft (optional) - '' // scheduledAt (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + sdk.MessagePriority.Normal // priority (optional) ); diff --git a/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md index 9e821e4436..721ba324de 100644 --- a/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-php/examples/databases/update-string-attribute.md @@ -16,6 +16,6 @@ $result = $databases->updateStringAttribute( key: '', required: false, default: '<DEFAULT>', - size: null, // optional + size: 1, // optional newKey: '' // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-php/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-php/examples/functions/download-deployment.md deleted file mode 100644 index 83c8bb756f..0000000000 --- a/docs/examples/1.6.x/server-php/examples/functions/download-deployment.md +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -use Appwrite\Client; -use Appwrite\Services\Functions; - -$client = (new Client()) - ->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - ->setProject('<YOUR_PROJECT_ID>') // Your project ID - ->setKey('<YOUR_API_KEY>'); // Your secret API key - -$functions = new Functions($client); - -$result = $functions->downloadDeployment( - functionId: '<FUNCTION_ID>', - deploymentId: '<DEPLOYMENT_ID>' -); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-php/examples/functions/get-template.md b/docs/examples/1.6.x/server-php/examples/functions/get-template.md deleted file mode 100644 index 421557dcd2..0000000000 --- a/docs/examples/1.6.x/server-php/examples/functions/get-template.md +++ /dev/null @@ -1,14 +0,0 @@ -<?php - -use Appwrite\Client; -use Appwrite\Services\Functions; - -$client = (new Client()) - ->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - ->setProject('<YOUR_PROJECT_ID>'); // Your project ID - -$functions = new Functions($client); - -$result = $functions->getTemplate( - templateId: '<TEMPLATE_ID>' -); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-php/examples/functions/list-templates.md b/docs/examples/1.6.x/server-php/examples/functions/list-templates.md deleted file mode 100644 index a661903306..0000000000 --- a/docs/examples/1.6.x/server-php/examples/functions/list-templates.md +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -use Appwrite\Client; -use Appwrite\Services\Functions; - -$client = (new Client()) - ->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint - ->setProject('<YOUR_PROJECT_ID>'); // Your project ID - -$functions = new Functions($client); - -$result = $functions->listTemplates( - runtimes: [], // optional - useCases: [], // optional - limit: 1, // optional - offset: 0 // optional -); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-php/examples/messaging/create-push.md b/docs/examples/1.6.x/server-php/examples/messaging/create-push.md index 7838576df0..9aaf6ad4ad 100644 --- a/docs/examples/1.6.x/server-php/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-php/examples/messaging/create-push.md @@ -12,8 +12,8 @@ $messaging = new Messaging($client); $result = $messaging->createPush( messageId: '<MESSAGE_ID>', - title: '<TITLE>', - body: '<BODY>', + title: '<TITLE>', // optional + body: '<BODY>', // optional topics: [], // optional users: [], // optional targets: [], // optional @@ -24,7 +24,10 @@ $result = $messaging->createPush( sound: '<SOUND>', // optional color: '<COLOR>', // optional tag: '<TAG>', // optional - badge: '<BADGE>', // optional + badge: null, // optional draft: false, // optional - scheduledAt: '' // optional + scheduledAt: '', // optional + contentAvailable: false, // optional + critical: false, // optional + priority: MessagePriority::NORMAL() // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-php/examples/messaging/update-push.md b/docs/examples/1.6.x/server-php/examples/messaging/update-push.md index 09a4d96042..7546fc8668 100644 --- a/docs/examples/1.6.x/server-php/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-php/examples/messaging/update-push.md @@ -26,5 +26,8 @@ $result = $messaging->updatePush( tag: '<TAG>', // optional badge: null, // optional draft: false, // optional - scheduledAt: '' // optional + scheduledAt: '', // optional + contentAvailable: false, // optional + critical: false, // optional + priority: MessagePriority::NORMAL() // optional ); \ No newline at end of file diff --git a/docs/examples/1.6.x/server-python/examples/account/create-anonymous-session.md b/docs/examples/1.6.x/server-python/examples/account/create-anonymous-session.md index 36ed47de01..ce5a92ad18 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-anonymous-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-anonymous-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-email-password-session.md b/docs/examples/1.6.x/server-python/examples/account/create-email-password-session.md index b85cc3d365..5e869fd40c 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-email-password-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-email-password-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-email-token.md b/docs/examples/1.6.x/server-python/examples/account/create-email-token.md index 4c18324ef3..5cf2bfb085 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-email-token.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-email-token.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-j-w-t.md b/docs/examples/1.6.x/server-python/examples/account/create-j-w-t.md index 2121514562..c737f1b8e9 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-j-w-t.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-j-w-t.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-magic-u-r-l-token.md b/docs/examples/1.6.x/server-python/examples/account/create-magic-u-r-l-token.md index c0154182e6..00778172bb 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-magic-u-r-l-token.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-magic-u-r-l-token.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-mfa-authenticator.md b/docs/examples/1.6.x/server-python/examples/account/create-mfa-authenticator.md index 16a8e2ebae..a6f09eb4f0 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-mfa-authenticator.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account from appwrite.enums import AuthenticatorType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/account/create-mfa-challenge.md b/docs/examples/1.6.x/server-python/examples/account/create-mfa-challenge.md index 017fdd28cc..deb4c9c600 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-mfa-challenge.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-mfa-challenge.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account from appwrite.enums import AuthenticationFactor client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/account/create-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/account/create-mfa-recovery-codes.md index 452b47f72f..a149cb95b7 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-o-auth2token.md b/docs/examples/1.6.x/server-python/examples/account/create-o-auth2token.md index 0cc89df216..fa11d31c31 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-o-auth2token.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-o-auth2token.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account from appwrite.enums import OAuthProvider client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/account/create-phone-token.md b/docs/examples/1.6.x/server-python/examples/account/create-phone-token.md index 30c80df6be..d242d71bc1 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-phone-token.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-phone-token.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-phone-verification.md b/docs/examples/1.6.x/server-python/examples/account/create-phone-verification.md index fd0a2620aa..bb2058eb2a 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-phone-verification.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-phone-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-recovery.md b/docs/examples/1.6.x/server-python/examples/account/create-recovery.md index e9613cd947..3d215a400e 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-recovery.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-recovery.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-session.md b/docs/examples/1.6.x/server-python/examples/account/create-session.md index d129e1000c..d00e8cb899 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create-verification.md b/docs/examples/1.6.x/server-python/examples/account/create-verification.md index 5ff238f674..329d19e6fd 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create-verification.md +++ b/docs/examples/1.6.x/server-python/examples/account/create-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/create.md b/docs/examples/1.6.x/server-python/examples/account/create.md index 33b6f3fe23..39b33c62ee 100644 --- a/docs/examples/1.6.x/server-python/examples/account/create.md +++ b/docs/examples/1.6.x/server-python/examples/account/create.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/delete-identity.md b/docs/examples/1.6.x/server-python/examples/account/delete-identity.md index ef57289443..3556122de8 100644 --- a/docs/examples/1.6.x/server-python/examples/account/delete-identity.md +++ b/docs/examples/1.6.x/server-python/examples/account/delete-identity.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/delete-mfa-authenticator.md b/docs/examples/1.6.x/server-python/examples/account/delete-mfa-authenticator.md index 0fbe8c7475..939ea718c7 100644 --- a/docs/examples/1.6.x/server-python/examples/account/delete-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-python/examples/account/delete-mfa-authenticator.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account from appwrite.enums import AuthenticatorType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/account/delete-session.md b/docs/examples/1.6.x/server-python/examples/account/delete-session.md index fa0049c6e4..9ddb4431d3 100644 --- a/docs/examples/1.6.x/server-python/examples/account/delete-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/delete-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/delete-sessions.md b/docs/examples/1.6.x/server-python/examples/account/delete-sessions.md index 6ebe286c89..751ab9bb2d 100644 --- a/docs/examples/1.6.x/server-python/examples/account/delete-sessions.md +++ b/docs/examples/1.6.x/server-python/examples/account/delete-sessions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/get-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/account/get-mfa-recovery-codes.md index ec705952b2..f70b968274 100644 --- a/docs/examples/1.6.x/server-python/examples/account/get-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/account/get-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/get-prefs.md b/docs/examples/1.6.x/server-python/examples/account/get-prefs.md index 67d0741733..52df6450dc 100644 --- a/docs/examples/1.6.x/server-python/examples/account/get-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/account/get-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/get-session.md b/docs/examples/1.6.x/server-python/examples/account/get-session.md index f7ae72d69e..f38466fb34 100644 --- a/docs/examples/1.6.x/server-python/examples/account/get-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/get-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/get.md b/docs/examples/1.6.x/server-python/examples/account/get.md index 9ded8e96cb..b414047e2d 100644 --- a/docs/examples/1.6.x/server-python/examples/account/get.md +++ b/docs/examples/1.6.x/server-python/examples/account/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/list-identities.md b/docs/examples/1.6.x/server-python/examples/account/list-identities.md index c51da2cb67..4bf9beb1b2 100644 --- a/docs/examples/1.6.x/server-python/examples/account/list-identities.md +++ b/docs/examples/1.6.x/server-python/examples/account/list-identities.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/list-logs.md b/docs/examples/1.6.x/server-python/examples/account/list-logs.md index 750f97716a..5d8c27aded 100644 --- a/docs/examples/1.6.x/server-python/examples/account/list-logs.md +++ b/docs/examples/1.6.x/server-python/examples/account/list-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/list-mfa-factors.md b/docs/examples/1.6.x/server-python/examples/account/list-mfa-factors.md index 2220475b9f..ba3796bf65 100644 --- a/docs/examples/1.6.x/server-python/examples/account/list-mfa-factors.md +++ b/docs/examples/1.6.x/server-python/examples/account/list-mfa-factors.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/list-sessions.md b/docs/examples/1.6.x/server-python/examples/account/list-sessions.md index b3427c09ce..74733138cd 100644 --- a/docs/examples/1.6.x/server-python/examples/account/list-sessions.md +++ b/docs/examples/1.6.x/server-python/examples/account/list-sessions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-email.md b/docs/examples/1.6.x/server-python/examples/account/update-email.md index b0a2a16002..004d071da1 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-email.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-email.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-m-f-a.md b/docs/examples/1.6.x/server-python/examples/account/update-m-f-a.md index 561e7cc431..2f9321c485 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-m-f-a.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-m-f-a.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-magic-u-r-l-session.md b/docs/examples/1.6.x/server-python/examples/account/update-magic-u-r-l-session.md index f6b69b03cc..ca8e8e51a3 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-magic-u-r-l-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-magic-u-r-l-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-mfa-authenticator.md b/docs/examples/1.6.x/server-python/examples/account/update-mfa-authenticator.md index 42b91f1d46..a5a951906c 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-mfa-authenticator.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account from appwrite.enums import AuthenticatorType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/account/update-mfa-challenge.md b/docs/examples/1.6.x/server-python/examples/account/update-mfa-challenge.md index 5964df42f8..d28a2518d7 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-mfa-challenge.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-mfa-challenge.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/account/update-mfa-recovery-codes.md index 4f0b1362a0..38cb41ca8d 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-name.md b/docs/examples/1.6.x/server-python/examples/account/update-name.md index d0027a8400..9b4bf8291d 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-name.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-name.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-password.md b/docs/examples/1.6.x/server-python/examples/account/update-password.md index 888349e207..ecb4228df0 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-password.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-password.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-phone-session.md b/docs/examples/1.6.x/server-python/examples/account/update-phone-session.md index 404d2b458c..d29ab28e39 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-phone-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-phone-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-phone-verification.md b/docs/examples/1.6.x/server-python/examples/account/update-phone-verification.md index 41ceb4bc05..e64d79f6bd 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-phone-verification.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-phone-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-phone.md b/docs/examples/1.6.x/server-python/examples/account/update-phone.md index b7414e613e..65a6a387b3 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-phone.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-phone.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-prefs.md b/docs/examples/1.6.x/server-python/examples/account/update-prefs.md index f69dc12b33..c3683007b7 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-recovery.md b/docs/examples/1.6.x/server-python/examples/account/update-recovery.md index a3314134e6..2493dc5e53 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-recovery.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-recovery.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-session.md b/docs/examples/1.6.x/server-python/examples/account/update-session.md index 3768326e98..ee3a2f7543 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-session.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-status.md b/docs/examples/1.6.x/server-python/examples/account/update-status.md index 4f9add80f7..c8318a43ce 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-status.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-status.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/account/update-verification.md b/docs/examples/1.6.x/server-python/examples/account/update-verification.md index 35faf53cb8..63a7f26322 100644 --- a/docs/examples/1.6.x/server-python/examples/account/update-verification.md +++ b/docs/examples/1.6.x/server-python/examples/account/update-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.account import Account client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-browser.md b/docs/examples/1.6.x/server-python/examples/avatars/get-browser.md index 91dde3bbb8..7ed831835f 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-browser.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-browser.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars from appwrite.enums import Browser client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-credit-card.md b/docs/examples/1.6.x/server-python/examples/avatars/get-credit-card.md index cec2f61a20..aa66b86b2d 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-credit-card.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-credit-card.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars from appwrite.enums import CreditCard client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-favicon.md b/docs/examples/1.6.x/server-python/examples/avatars/get-favicon.md index 4aa0177a26..2c6a67e2f2 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-favicon.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-favicon.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-flag.md b/docs/examples/1.6.x/server-python/examples/avatars/get-flag.md index 6b12dac6be..435c8550f7 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-flag.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-flag.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars from appwrite.enums import Flag client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-image.md b/docs/examples/1.6.x/server-python/examples/avatars/get-image.md index 202955c2fc..ee9e0cb15e 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-image.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-image.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-initials.md b/docs/examples/1.6.x/server-python/examples/avatars/get-initials.md index 233da1b131..edcbbb33ec 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-initials.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-initials.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/avatars/get-q-r.md b/docs/examples/1.6.x/server-python/examples/avatars/get-q-r.md index 12963947d2..7f6da32ddf 100644 --- a/docs/examples/1.6.x/server-python/examples/avatars/get-q-r.md +++ b/docs/examples/1.6.x/server-python/examples/avatars/get-q-r.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.avatars import Avatars client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-boolean-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-boolean-attribute.md index 183a2b6487..2b4209db9d 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-boolean-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-boolean-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-collection.md b/docs/examples/1.6.x/server-python/examples/databases/create-collection.md index fd9e3a6c0c..99c44a2f9f 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-collection.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-collection.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-datetime-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-datetime-attribute.md index 7435742e1c..db81c021e2 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-datetime-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-datetime-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-document.md b/docs/examples/1.6.x/server-python/examples/databases/create-document.md index bd3993f162..22f2c07396 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-document.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-document.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-email-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-email-attribute.md index f4b427e294..2e28e0bfff 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-email-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-email-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-enum-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-enum-attribute.md index dce63558da..b1efdc7dc3 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-enum-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-enum-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-float-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-float-attribute.md index a658bd8f4c..b36863b8ee 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-float-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-float-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-index.md b/docs/examples/1.6.x/server-python/examples/databases/create-index.md index 015b762bbc..9885c06e95 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-index.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-index.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases from appwrite.enums import IndexType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-integer-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-integer-attribute.md index 9f409e484e..8cb140a7b9 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-integer-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-integer-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-ip-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-ip-attribute.md index ab4d357447..d4b4ab6528 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-ip-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-ip-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-relationship-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-relationship-attribute.md index 76b5db1c45..4172c27249 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-relationship-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-relationship-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases from appwrite.enums import RelationshipType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-string-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-string-attribute.md index d6f7f94627..e69687124d 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-string-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-string-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create-url-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/create-url-attribute.md index 3b105d80e8..4ad03c4010 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create-url-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create-url-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/create.md b/docs/examples/1.6.x/server-python/examples/databases/create.md index a4ddc92cc6..d5cbb99eed 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/create.md +++ b/docs/examples/1.6.x/server-python/examples/databases/create.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/delete-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/delete-attribute.md index 7f490b2350..b317ba9dd4 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/delete-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/delete-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/delete-collection.md b/docs/examples/1.6.x/server-python/examples/databases/delete-collection.md index c3083a51bc..ab274c6bdf 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/delete-collection.md +++ b/docs/examples/1.6.x/server-python/examples/databases/delete-collection.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/delete-document.md b/docs/examples/1.6.x/server-python/examples/databases/delete-document.md index c3e296aef2..69151aad9e 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/delete-document.md +++ b/docs/examples/1.6.x/server-python/examples/databases/delete-document.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/delete-index.md b/docs/examples/1.6.x/server-python/examples/databases/delete-index.md index d5a12c140e..2ed0165b36 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/delete-index.md +++ b/docs/examples/1.6.x/server-python/examples/databases/delete-index.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/delete.md b/docs/examples/1.6.x/server-python/examples/databases/delete.md index 41d5f18f8a..e7e988a9a5 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/delete.md +++ b/docs/examples/1.6.x/server-python/examples/databases/delete.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/get-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/get-attribute.md index e505fe9a38..a717552659 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/get-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/get-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/get-collection.md b/docs/examples/1.6.x/server-python/examples/databases/get-collection.md index 7be57ea193..f63298ebed 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/get-collection.md +++ b/docs/examples/1.6.x/server-python/examples/databases/get-collection.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/get-document.md b/docs/examples/1.6.x/server-python/examples/databases/get-document.md index 83faadec38..acdc25de7e 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/get-document.md +++ b/docs/examples/1.6.x/server-python/examples/databases/get-document.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/get-index.md b/docs/examples/1.6.x/server-python/examples/databases/get-index.md index 6038868b41..ca5a9958ad 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/get-index.md +++ b/docs/examples/1.6.x/server-python/examples/databases/get-index.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/get.md b/docs/examples/1.6.x/server-python/examples/databases/get.md index 8fe2358be7..deadf6ab41 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/get.md +++ b/docs/examples/1.6.x/server-python/examples/databases/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/list-attributes.md b/docs/examples/1.6.x/server-python/examples/databases/list-attributes.md index a29aefa015..245ec60c19 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/list-attributes.md +++ b/docs/examples/1.6.x/server-python/examples/databases/list-attributes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/list-collections.md b/docs/examples/1.6.x/server-python/examples/databases/list-collections.md index 0e613321c2..ca18267250 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/list-collections.md +++ b/docs/examples/1.6.x/server-python/examples/databases/list-collections.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/list-documents.md b/docs/examples/1.6.x/server-python/examples/databases/list-documents.md index dee130e65f..41f0380e15 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/list-documents.md +++ b/docs/examples/1.6.x/server-python/examples/databases/list-documents.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/list-indexes.md b/docs/examples/1.6.x/server-python/examples/databases/list-indexes.md index 40578a14de..bf18bd1c95 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/list-indexes.md +++ b/docs/examples/1.6.x/server-python/examples/databases/list-indexes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/list.md b/docs/examples/1.6.x/server-python/examples/databases/list.md index aa934b2b12..11669b3453 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/list.md +++ b/docs/examples/1.6.x/server-python/examples/databases/list.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-boolean-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-boolean-attribute.md index 553d94b109..c9300ea57d 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-boolean-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-boolean-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-collection.md b/docs/examples/1.6.x/server-python/examples/databases/update-collection.md index 3432b6bf18..d9297285ee 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-collection.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-collection.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-datetime-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-datetime-attribute.md index f9056d2c39..96c7fb5439 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-datetime-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-datetime-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-document.md b/docs/examples/1.6.x/server-python/examples/databases/update-document.md index 07bba7678c..7b9cce9513 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-document.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-document.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-email-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-email-attribute.md index 45a8d0d9bc..5b042d4b72 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-email-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-email-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-enum-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-enum-attribute.md index c07f3754d8..caa1b4ecdb 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-enum-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-enum-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-float-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-float-attribute.md index fa1767e893..8f8a35a2c8 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-float-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-float-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-integer-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-integer-attribute.md index 0db97070ed..125cf825bf 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-integer-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-integer-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-ip-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-ip-attribute.md index 135dbd82ea..a2b8bad201 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-ip-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-ip-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-relationship-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-relationship-attribute.md index bc528f17dd..0aacc139a0 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-relationship-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-relationship-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md index bbe7ddb19f..c85eb25f59 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-string-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint @@ -13,6 +14,6 @@ result = databases.update_string_attribute( key = '', required = False, default = '<DEFAULT>', - size = None, # optional + size = 1, # optional new_key = '' # optional ) diff --git a/docs/examples/1.6.x/server-python/examples/databases/update-url-attribute.md b/docs/examples/1.6.x/server-python/examples/databases/update-url-attribute.md index 8e3a28de1f..53da6ae45f 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update-url-attribute.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update-url-attribute.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/databases/update.md b/docs/examples/1.6.x/server-python/examples/databases/update.md index 765f28a3fc..da59776b3e 100644 --- a/docs/examples/1.6.x/server-python/examples/databases/update.md +++ b/docs/examples/1.6.x/server-python/examples/databases/update.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.databases import Databases client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/create-build.md b/docs/examples/1.6.x/server-python/examples/functions/create-build.md index c4eb9d0a20..ce2ffb72f5 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/create-build.md +++ b/docs/examples/1.6.x/server-python/examples/functions/create-build.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/create-deployment.md b/docs/examples/1.6.x/server-python/examples/functions/create-deployment.md index da9b559b2f..c86fdf679d 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/create-deployment.md +++ b/docs/examples/1.6.x/server-python/examples/functions/create-deployment.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions from appwrite.input_file import InputFile client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/functions/create-execution.md b/docs/examples/1.6.x/server-python/examples/functions/create-execution.md index e1decb9755..cb3fddd02b 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/create-execution.md +++ b/docs/examples/1.6.x/server-python/examples/functions/create-execution.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/create-variable.md b/docs/examples/1.6.x/server-python/examples/functions/create-variable.md index cd73e30c03..101ecdf315 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/create-variable.md +++ b/docs/examples/1.6.x/server-python/examples/functions/create-variable.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/create.md b/docs/examples/1.6.x/server-python/examples/functions/create.md index a65b87dd4c..f10a953ca8 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/create.md +++ b/docs/examples/1.6.x/server-python/examples/functions/create.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions from appwrite.enums import client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/functions/delete-deployment.md b/docs/examples/1.6.x/server-python/examples/functions/delete-deployment.md index 780ce9d7c8..f98bd60a9b 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/delete-deployment.md +++ b/docs/examples/1.6.x/server-python/examples/functions/delete-deployment.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/delete-execution.md b/docs/examples/1.6.x/server-python/examples/functions/delete-execution.md index 7c3ea09a0f..b723fd6c47 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/delete-execution.md +++ b/docs/examples/1.6.x/server-python/examples/functions/delete-execution.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/delete-variable.md b/docs/examples/1.6.x/server-python/examples/functions/delete-variable.md index 646a0f325b..e17afed363 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/delete-variable.md +++ b/docs/examples/1.6.x/server-python/examples/functions/delete-variable.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/delete.md b/docs/examples/1.6.x/server-python/examples/functions/delete.md index 2950ed0235..a34d476744 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/delete.md +++ b/docs/examples/1.6.x/server-python/examples/functions/delete.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-python/examples/functions/download-deployment.md deleted file mode 100644 index f9d395451e..0000000000 --- a/docs/examples/1.6.x/server-python/examples/functions/download-deployment.md +++ /dev/null @@ -1,13 +0,0 @@ -from appwrite.client import Client - -client = Client() -client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint -client.set_project('<YOUR_PROJECT_ID>') # Your project ID -client.set_key('<YOUR_API_KEY>') # Your secret API key - -functions = Functions(client) - -result = functions.download_deployment( - function_id = '<FUNCTION_ID>', - deployment_id = '<DEPLOYMENT_ID>' -) diff --git a/docs/examples/1.6.x/server-python/examples/functions/get-deployment-download.md b/docs/examples/1.6.x/server-python/examples/functions/get-deployment-download.md index 490d9521df..90f029aff5 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/get-deployment-download.md +++ b/docs/examples/1.6.x/server-python/examples/functions/get-deployment-download.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/get-deployment.md b/docs/examples/1.6.x/server-python/examples/functions/get-deployment.md index 8846888f0f..0617b0429c 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/get-deployment.md +++ b/docs/examples/1.6.x/server-python/examples/functions/get-deployment.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/get-execution.md b/docs/examples/1.6.x/server-python/examples/functions/get-execution.md index f3dfc0f4ee..0a9a347409 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/get-execution.md +++ b/docs/examples/1.6.x/server-python/examples/functions/get-execution.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/get-template.md b/docs/examples/1.6.x/server-python/examples/functions/get-template.md deleted file mode 100644 index bea5b6ab03..0000000000 --- a/docs/examples/1.6.x/server-python/examples/functions/get-template.md +++ /dev/null @@ -1,11 +0,0 @@ -from appwrite.client import Client - -client = Client() -client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint -client.set_project('<YOUR_PROJECT_ID>') # Your project ID - -functions = Functions(client) - -result = functions.get_template( - template_id = '<TEMPLATE_ID>' -) diff --git a/docs/examples/1.6.x/server-python/examples/functions/get-variable.md b/docs/examples/1.6.x/server-python/examples/functions/get-variable.md index fd903f3045..174c8b27bf 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/get-variable.md +++ b/docs/examples/1.6.x/server-python/examples/functions/get-variable.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/get.md b/docs/examples/1.6.x/server-python/examples/functions/get.md index cb765e42a1..a463fa6b28 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/get.md +++ b/docs/examples/1.6.x/server-python/examples/functions/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-deployments.md b/docs/examples/1.6.x/server-python/examples/functions/list-deployments.md index f776345f11..4d8feea927 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list-deployments.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list-deployments.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-executions.md b/docs/examples/1.6.x/server-python/examples/functions/list-executions.md index 0012bafc8f..293bab047a 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list-executions.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list-executions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-runtimes.md b/docs/examples/1.6.x/server-python/examples/functions/list-runtimes.md index edad1a9178..b6247330d0 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list-runtimes.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list-runtimes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-specifications.md b/docs/examples/1.6.x/server-python/examples/functions/list-specifications.md index a9c7417654..5e1ec7fd61 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list-specifications.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list-specifications.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-templates.md b/docs/examples/1.6.x/server-python/examples/functions/list-templates.md deleted file mode 100644 index b3ee38aef7..0000000000 --- a/docs/examples/1.6.x/server-python/examples/functions/list-templates.md +++ /dev/null @@ -1,14 +0,0 @@ -from appwrite.client import Client - -client = Client() -client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint -client.set_project('<YOUR_PROJECT_ID>') # Your project ID - -functions = Functions(client) - -result = functions.list_templates( - runtimes = [], # optional - use_cases = [], # optional - limit = 1, # optional - offset = 0 # optional -) diff --git a/docs/examples/1.6.x/server-python/examples/functions/list-variables.md b/docs/examples/1.6.x/server-python/examples/functions/list-variables.md index 188c17bb6a..ee1a516c5e 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list-variables.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list-variables.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/list.md b/docs/examples/1.6.x/server-python/examples/functions/list.md index 5b315e18cc..0b5f18d70a 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/list.md +++ b/docs/examples/1.6.x/server-python/examples/functions/list.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/update-deployment-build.md b/docs/examples/1.6.x/server-python/examples/functions/update-deployment-build.md index a8d93b8416..c69cd7c181 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/update-deployment-build.md +++ b/docs/examples/1.6.x/server-python/examples/functions/update-deployment-build.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/update-deployment.md b/docs/examples/1.6.x/server-python/examples/functions/update-deployment.md index 9fce384715..0f4c96e85c 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/update-deployment.md +++ b/docs/examples/1.6.x/server-python/examples/functions/update-deployment.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/update-variable.md b/docs/examples/1.6.x/server-python/examples/functions/update-variable.md index 238fc91eff..bcab3685a2 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/update-variable.md +++ b/docs/examples/1.6.x/server-python/examples/functions/update-variable.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/functions/update.md b/docs/examples/1.6.x/server-python/examples/functions/update.md index 5f2a70baaa..a7282412cc 100644 --- a/docs/examples/1.6.x/server-python/examples/functions/update.md +++ b/docs/examples/1.6.x/server-python/examples/functions/update.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.functions import Functions client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/graphql/mutation.md b/docs/examples/1.6.x/server-python/examples/graphql/mutation.md index 0ec3d3eefc..e05f602719 100644 --- a/docs/examples/1.6.x/server-python/examples/graphql/mutation.md +++ b/docs/examples/1.6.x/server-python/examples/graphql/mutation.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.graphql import Graphql client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/graphql/query.md b/docs/examples/1.6.x/server-python/examples/graphql/query.md index 95709fd694..c8f3c78a1a 100644 --- a/docs/examples/1.6.x/server-python/examples/graphql/query.md +++ b/docs/examples/1.6.x/server-python/examples/graphql/query.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.graphql import Graphql client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-antivirus.md b/docs/examples/1.6.x/server-python/examples/health/get-antivirus.md index ff93ceac76..7bc0475abf 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-antivirus.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-antivirus.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-cache.md b/docs/examples/1.6.x/server-python/examples/health/get-cache.md index fa2a6daa5c..7e69825ecf 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-cache.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-cache.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-certificate.md b/docs/examples/1.6.x/server-python/examples/health/get-certificate.md index 2a73583361..f6a713e2f3 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-certificate.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-certificate.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-d-b.md b/docs/examples/1.6.x/server-python/examples/health/get-d-b.md index 18e3968246..a23a073ac7 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-d-b.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-d-b.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-failed-jobs.md b/docs/examples/1.6.x/server-python/examples/health/get-failed-jobs.md index ce33c8c9bd..d0fe64f7f3 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-failed-jobs.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-failed-jobs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health from appwrite.enums import client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/health/get-pub-sub.md b/docs/examples/1.6.x/server-python/examples/health/get-pub-sub.md index db66c7f676..109b2889f6 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-pub-sub.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-pub-sub.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-builds.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-builds.md index 9daed589f8..b1d4d62116 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-builds.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-builds.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-certificates.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-certificates.md index a7d35bc9f4..99f52b8eda 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-certificates.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-certificates.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-databases.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-databases.md index 50f8943fa6..7d5e5a0c58 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-databases.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-databases.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-deletes.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-deletes.md index b6e6a4d4a4..d677af582e 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-deletes.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-deletes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-functions.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-functions.md index 5868b3cd68..3ffc4b8f52 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-functions.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-functions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-logs.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-logs.md index 254fe23331..0cb6417f4f 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-logs.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-mails.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-mails.md index c6ab409c9b..97a501cc1c 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-mails.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-mails.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-messaging.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-messaging.md index 1007913866..ea93eab6dc 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-messaging.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-messaging.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-migrations.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-migrations.md index db59028f37..09e35dfa9d 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-migrations.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-migrations.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-usage-dump.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-usage-dump.md index cc31b4f5af..dabb79ae96 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-usage-dump.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-usage-dump.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-usage.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-usage.md index 67d9e64c14..dbee75fce0 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-usage.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-usage.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue-webhooks.md b/docs/examples/1.6.x/server-python/examples/health/get-queue-webhooks.md index 918846738d..1072a20def 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue-webhooks.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue-webhooks.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-queue.md b/docs/examples/1.6.x/server-python/examples/health/get-queue.md index 61e5a40caa..aafe7c7dd0 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-queue.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-queue.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-storage-local.md b/docs/examples/1.6.x/server-python/examples/health/get-storage-local.md index 276c3058f9..d3b94b2177 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-storage-local.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-storage-local.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-storage.md b/docs/examples/1.6.x/server-python/examples/health/get-storage.md index b2de63b72f..65af2f959d 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-storage.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-storage.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get-time.md b/docs/examples/1.6.x/server-python/examples/health/get-time.md index 40893057cb..d63beb988b 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get-time.md +++ b/docs/examples/1.6.x/server-python/examples/health/get-time.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/health/get.md b/docs/examples/1.6.x/server-python/examples/health/get.md index f41e0e3a9b..f5c494e12d 100644 --- a/docs/examples/1.6.x/server-python/examples/health/get.md +++ b/docs/examples/1.6.x/server-python/examples/health/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.health import Health client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/get.md b/docs/examples/1.6.x/server-python/examples/locale/get.md index fc048ddcc9..a44f4974ac 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/get.md +++ b/docs/examples/1.6.x/server-python/examples/locale/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-codes.md b/docs/examples/1.6.x/server-python/examples/locale/list-codes.md index d516538cb9..12cd12ee70 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-codes.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-continents.md b/docs/examples/1.6.x/server-python/examples/locale/list-continents.md index f6d8495527..ea4ac5312d 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-continents.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-continents.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-countries-e-u.md b/docs/examples/1.6.x/server-python/examples/locale/list-countries-e-u.md index 8bdac2e5e3..7fb6aaa59e 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-countries-e-u.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-countries-e-u.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-countries-phones.md b/docs/examples/1.6.x/server-python/examples/locale/list-countries-phones.md index 516d822b59..aafdb3d547 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-countries-phones.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-countries-phones.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-countries.md b/docs/examples/1.6.x/server-python/examples/locale/list-countries.md index 8fcbe1aeb9..a2f1ec458d 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-countries.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-countries.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-currencies.md b/docs/examples/1.6.x/server-python/examples/locale/list-currencies.md index 4708498efb..39267c663c 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-currencies.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-currencies.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/locale/list-languages.md b/docs/examples/1.6.x/server-python/examples/locale/list-languages.md index 9583cd8b3f..6dec1b9072 100644 --- a/docs/examples/1.6.x/server-python/examples/locale/list-languages.md +++ b/docs/examples/1.6.x/server-python/examples/locale/list-languages.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.locale import Locale client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-apns-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-apns-provider.md index 022209d1e6..700e909c44 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-apns-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-apns-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-email.md b/docs/examples/1.6.x/server-python/examples/messaging/create-email.md index 38005a3736..92353e22c2 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-email.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-email.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-fcm-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-fcm-provider.md index 84c38eae98..d13ba0213d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-fcm-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-fcm-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-mailgun-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-mailgun-provider.md index fa94da96c9..83899716d7 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-mailgun-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-mailgun-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-msg91provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-msg91provider.md index 0cffc4e491..117c46edca 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-msg91provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-msg91provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-push.md b/docs/examples/1.6.x/server-python/examples/messaging/create-push.md index ffed825a3d..d4051859df 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-push.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint @@ -9,8 +10,8 @@ messaging = Messaging(client) result = messaging.create_push( message_id = '<MESSAGE_ID>', - title = '<TITLE>', - body = '<BODY>', + title = '<TITLE>', # optional + body = '<BODY>', # optional topics = [], # optional users = [], # optional targets = [], # optional @@ -21,7 +22,10 @@ result = messaging.create_push( sound = '<SOUND>', # optional color = '<COLOR>', # optional tag = '<TAG>', # optional - badge = '<BADGE>', # optional + badge = None, # optional draft = False, # optional - scheduled_at = '' # optional + scheduled_at = '', # optional + content_available = False, # optional + critical = False, # optional + priority = MessagePriority.NORMAL # optional ) diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-sendgrid-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-sendgrid-provider.md index 6e9b812736..5d20cde78d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-sendgrid-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-sendgrid-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-sms.md b/docs/examples/1.6.x/server-python/examples/messaging/create-sms.md index c3e7fe70bf..c7e66d8c75 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-sms.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-sms.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-smtp-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-smtp-provider.md index 24108d251f..85c58236c0 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-smtp-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-smtp-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-subscriber.md b/docs/examples/1.6.x/server-python/examples/messaging/create-subscriber.md index 81b0c5f468..cb8f4f748d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-subscriber.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-subscriber.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-telesign-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-telesign-provider.md index b06033c5c5..b602213b78 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-telesign-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-telesign-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-textmagic-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-textmagic-provider.md index 6dc1030cd3..03287e8fac 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-textmagic-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-textmagic-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-topic.md b/docs/examples/1.6.x/server-python/examples/messaging/create-topic.md index b0184b53b4..4dd16da3f0 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-topic.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-topic.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-twilio-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-twilio-provider.md index c73e941945..524348f085 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-twilio-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-twilio-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/create-vonage-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/create-vonage-provider.md index cfee0ad7a4..68416bd8c3 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/create-vonage-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/create-vonage-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/delete-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/delete-provider.md index 4d2bd6d015..2a1840d64d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/delete-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/delete-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/delete-subscriber.md b/docs/examples/1.6.x/server-python/examples/messaging/delete-subscriber.md index 5d404d1875..94085ef86b 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/delete-subscriber.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/delete-subscriber.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/delete-topic.md b/docs/examples/1.6.x/server-python/examples/messaging/delete-topic.md index b270b2a708..1c2f5635da 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/delete-topic.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/delete-topic.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/delete.md b/docs/examples/1.6.x/server-python/examples/messaging/delete.md index c62c8c0d21..aee928a792 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/delete.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/delete.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/get-message.md b/docs/examples/1.6.x/server-python/examples/messaging/get-message.md index 4b4ef39203..9e32d80623 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/get-message.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/get-message.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/get-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/get-provider.md index fdf94f0304..6bc85f2710 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/get-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/get-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/get-subscriber.md b/docs/examples/1.6.x/server-python/examples/messaging/get-subscriber.md index 7f8284f874..43185d7eb3 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/get-subscriber.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/get-subscriber.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/get-topic.md b/docs/examples/1.6.x/server-python/examples/messaging/get-topic.md index 57c465b883..dea6cbfb6b 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/get-topic.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/get-topic.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-message-logs.md b/docs/examples/1.6.x/server-python/examples/messaging/list-message-logs.md index 752e449806..1c2ab0b035 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-message-logs.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-message-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-messages.md b/docs/examples/1.6.x/server-python/examples/messaging/list-messages.md index 7219f0948e..8457f99ad5 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-messages.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-messages.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-provider-logs.md b/docs/examples/1.6.x/server-python/examples/messaging/list-provider-logs.md index 148814c46d..c8544fac1e 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-provider-logs.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-provider-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-providers.md b/docs/examples/1.6.x/server-python/examples/messaging/list-providers.md index 3e896954e4..258e7cd6e1 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-providers.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-providers.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-subscriber-logs.md b/docs/examples/1.6.x/server-python/examples/messaging/list-subscriber-logs.md index 7efaeadedf..d2049bd560 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-subscriber-logs.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-subscriber-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-subscribers.md b/docs/examples/1.6.x/server-python/examples/messaging/list-subscribers.md index fe2442d806..ba9e09d8b9 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-subscribers.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-subscribers.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-targets.md b/docs/examples/1.6.x/server-python/examples/messaging/list-targets.md index 062257154c..b941ccbd31 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-targets.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-targets.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-topic-logs.md b/docs/examples/1.6.x/server-python/examples/messaging/list-topic-logs.md index de72a76a27..57ba7f8d31 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-topic-logs.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-topic-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/list-topics.md b/docs/examples/1.6.x/server-python/examples/messaging/list-topics.md index 1379708965..cb21567d42 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/list-topics.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/list-topics.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-apns-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-apns-provider.md index 2bfd3edfc1..3f0205d4ce 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-apns-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-apns-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-email.md b/docs/examples/1.6.x/server-python/examples/messaging/update-email.md index 6cff0ae6d8..b8f9d719c1 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-email.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-email.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-fcm-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-fcm-provider.md index 7ca9f381e6..862e579f53 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-fcm-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-fcm-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-mailgun-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-mailgun-provider.md index a89338df92..aa1d4e922c 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-mailgun-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-mailgun-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-msg91provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-msg91provider.md index 4c61950050..2d4efdbd78 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-msg91provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-msg91provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-push.md b/docs/examples/1.6.x/server-python/examples/messaging/update-push.md index 3c3965c3bd..12663533c3 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-push.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint @@ -23,5 +24,8 @@ result = messaging.update_push( tag = '<TAG>', # optional badge = None, # optional draft = False, # optional - scheduled_at = '' # optional + scheduled_at = '', # optional + content_available = False, # optional + critical = False, # optional + priority = MessagePriority.NORMAL # optional ) diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-sendgrid-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-sendgrid-provider.md index 8b67b7a44f..e528bd543d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-sendgrid-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-sendgrid-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-sms.md b/docs/examples/1.6.x/server-python/examples/messaging/update-sms.md index aadbd9aee8..7cb008736f 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-sms.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-sms.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-smtp-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-smtp-provider.md index 74232e983f..2d798d4e0e 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-smtp-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-smtp-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-telesign-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-telesign-provider.md index 264928178b..91de1f155c 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-telesign-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-telesign-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-textmagic-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-textmagic-provider.md index bbe4a93a50..c3031047c9 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-textmagic-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-textmagic-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-topic.md b/docs/examples/1.6.x/server-python/examples/messaging/update-topic.md index ee4d00411e..160ac26b6b 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-topic.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-topic.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-twilio-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-twilio-provider.md index 52eed3bb7b..865fcb5c1d 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-twilio-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-twilio-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/messaging/update-vonage-provider.md b/docs/examples/1.6.x/server-python/examples/messaging/update-vonage-provider.md index 7cb1594a81..8e01128bf2 100644 --- a/docs/examples/1.6.x/server-python/examples/messaging/update-vonage-provider.md +++ b/docs/examples/1.6.x/server-python/examples/messaging/update-vonage-provider.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.messaging import Messaging client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/create-bucket.md b/docs/examples/1.6.x/server-python/examples/storage/create-bucket.md index c6e9e33e02..7e321f12a3 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/create-bucket.md +++ b/docs/examples/1.6.x/server-python/examples/storage/create-bucket.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/create-file.md b/docs/examples/1.6.x/server-python/examples/storage/create-file.md index d275070bac..fa0b117b01 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/create-file.md +++ b/docs/examples/1.6.x/server-python/examples/storage/create-file.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage from appwrite.input_file import InputFile client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/storage/delete-bucket.md b/docs/examples/1.6.x/server-python/examples/storage/delete-bucket.md index 77d72eb915..8cddfb9202 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/delete-bucket.md +++ b/docs/examples/1.6.x/server-python/examples/storage/delete-bucket.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/delete-file.md b/docs/examples/1.6.x/server-python/examples/storage/delete-file.md index 775065dc38..08bba5ca4b 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/delete-file.md +++ b/docs/examples/1.6.x/server-python/examples/storage/delete-file.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/get-bucket.md b/docs/examples/1.6.x/server-python/examples/storage/get-bucket.md index adb78e8b92..79f903f244 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/get-bucket.md +++ b/docs/examples/1.6.x/server-python/examples/storage/get-bucket.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/get-file-download.md b/docs/examples/1.6.x/server-python/examples/storage/get-file-download.md index b419ea0164..1a82b26c70 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/get-file-download.md +++ b/docs/examples/1.6.x/server-python/examples/storage/get-file-download.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/get-file-preview.md b/docs/examples/1.6.x/server-python/examples/storage/get-file-preview.md index 2e3b2acdc6..40f32f1f10 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/get-file-preview.md +++ b/docs/examples/1.6.x/server-python/examples/storage/get-file-preview.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/get-file-view.md b/docs/examples/1.6.x/server-python/examples/storage/get-file-view.md index 9ce04e2a49..3947c76761 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/get-file-view.md +++ b/docs/examples/1.6.x/server-python/examples/storage/get-file-view.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/get-file.md b/docs/examples/1.6.x/server-python/examples/storage/get-file.md index 9f04ef4740..0c2d5e3b2c 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/get-file.md +++ b/docs/examples/1.6.x/server-python/examples/storage/get-file.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/list-buckets.md b/docs/examples/1.6.x/server-python/examples/storage/list-buckets.md index 84eab54286..88540cd5ce 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/list-buckets.md +++ b/docs/examples/1.6.x/server-python/examples/storage/list-buckets.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/list-files.md b/docs/examples/1.6.x/server-python/examples/storage/list-files.md index 8a2aa6d9a3..e26ac2e5f3 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/list-files.md +++ b/docs/examples/1.6.x/server-python/examples/storage/list-files.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/update-bucket.md b/docs/examples/1.6.x/server-python/examples/storage/update-bucket.md index 4eea2a9ccb..61388b0923 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/update-bucket.md +++ b/docs/examples/1.6.x/server-python/examples/storage/update-bucket.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/storage/update-file.md b/docs/examples/1.6.x/server-python/examples/storage/update-file.md index 0137af5849..336e8a0846 100644 --- a/docs/examples/1.6.x/server-python/examples/storage/update-file.md +++ b/docs/examples/1.6.x/server-python/examples/storage/update-file.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.storage import Storage client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/create-membership.md b/docs/examples/1.6.x/server-python/examples/teams/create-membership.md index 484629550d..1af9f252ab 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/create-membership.md +++ b/docs/examples/1.6.x/server-python/examples/teams/create-membership.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/create.md b/docs/examples/1.6.x/server-python/examples/teams/create.md index 544ee3a706..7085d39642 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/create.md +++ b/docs/examples/1.6.x/server-python/examples/teams/create.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/delete-membership.md b/docs/examples/1.6.x/server-python/examples/teams/delete-membership.md index 7f0cbd4ed6..adf065cd3c 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/delete-membership.md +++ b/docs/examples/1.6.x/server-python/examples/teams/delete-membership.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/delete.md b/docs/examples/1.6.x/server-python/examples/teams/delete.md index fc8415238e..762f532dbf 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/delete.md +++ b/docs/examples/1.6.x/server-python/examples/teams/delete.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/get-membership.md b/docs/examples/1.6.x/server-python/examples/teams/get-membership.md index 6075cc70d1..17bacff1d3 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/get-membership.md +++ b/docs/examples/1.6.x/server-python/examples/teams/get-membership.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/get-prefs.md b/docs/examples/1.6.x/server-python/examples/teams/get-prefs.md index d740e69e3b..035777d5cd 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/get-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/teams/get-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/get.md b/docs/examples/1.6.x/server-python/examples/teams/get.md index 6d44b80ee3..985924e10b 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/get.md +++ b/docs/examples/1.6.x/server-python/examples/teams/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/list-memberships.md b/docs/examples/1.6.x/server-python/examples/teams/list-memberships.md index f7a072a6d8..885a4c2822 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/list-memberships.md +++ b/docs/examples/1.6.x/server-python/examples/teams/list-memberships.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/list.md b/docs/examples/1.6.x/server-python/examples/teams/list.md index afb5de1241..c92d4c9c13 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/list.md +++ b/docs/examples/1.6.x/server-python/examples/teams/list.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/update-membership-status.md b/docs/examples/1.6.x/server-python/examples/teams/update-membership-status.md index ee6d211081..ae6e524da5 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/update-membership-status.md +++ b/docs/examples/1.6.x/server-python/examples/teams/update-membership-status.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/update-membership.md b/docs/examples/1.6.x/server-python/examples/teams/update-membership.md index 672615026e..c50f345b88 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/update-membership.md +++ b/docs/examples/1.6.x/server-python/examples/teams/update-membership.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/update-name.md b/docs/examples/1.6.x/server-python/examples/teams/update-name.md index 693654d3d7..d25c8db1f2 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/update-name.md +++ b/docs/examples/1.6.x/server-python/examples/teams/update-name.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/teams/update-prefs.md b/docs/examples/1.6.x/server-python/examples/teams/update-prefs.md index 46616011d6..9eca847a02 100644 --- a/docs/examples/1.6.x/server-python/examples/teams/update-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/teams/update-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.teams import Teams client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-argon2user.md b/docs/examples/1.6.x/server-python/examples/users/create-argon2user.md index 575aa42b30..3d65496573 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-argon2user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-argon2user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-bcrypt-user.md b/docs/examples/1.6.x/server-python/examples/users/create-bcrypt-user.md index f6cd2fe591..76532a98f0 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-bcrypt-user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-bcrypt-user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-j-w-t.md b/docs/examples/1.6.x/server-python/examples/users/create-j-w-t.md index a758d4e089..2e1fdf632f 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-j-w-t.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-j-w-t.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-m-d5user.md b/docs/examples/1.6.x/server-python/examples/users/create-m-d5user.md index cabf875938..da9d471fe2 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-m-d5user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-m-d5user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/users/create-mfa-recovery-codes.md index 606878f1e9..a4477b0406 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-p-h-pass-user.md b/docs/examples/1.6.x/server-python/examples/users/create-p-h-pass-user.md index 0d8f9907ac..363be4f92f 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-p-h-pass-user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-p-h-pass-user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-s-h-a-user.md b/docs/examples/1.6.x/server-python/examples/users/create-s-h-a-user.md index b0ae799b64..bb78ff7b5c 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-s-h-a-user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-s-h-a-user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-scrypt-modified-user.md b/docs/examples/1.6.x/server-python/examples/users/create-scrypt-modified-user.md index d7d17c4de0..1cfbcfc4b4 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-scrypt-modified-user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-scrypt-modified-user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-scrypt-user.md b/docs/examples/1.6.x/server-python/examples/users/create-scrypt-user.md index 507fb1f892..2d1e72bf77 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-scrypt-user.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-scrypt-user.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-session.md b/docs/examples/1.6.x/server-python/examples/users/create-session.md index a2ba12a580..bebd46b022 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-session.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create-target.md b/docs/examples/1.6.x/server-python/examples/users/create-target.md index 9ad8364ea3..c11c7ca233 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-target.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-target.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users from appwrite.enums import MessagingProviderType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/users/create-token.md b/docs/examples/1.6.x/server-python/examples/users/create-token.md index e2ef2f6969..00a0e78610 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create-token.md +++ b/docs/examples/1.6.x/server-python/examples/users/create-token.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/create.md b/docs/examples/1.6.x/server-python/examples/users/create.md index c3e7fd5558..c8dac9feae 100644 --- a/docs/examples/1.6.x/server-python/examples/users/create.md +++ b/docs/examples/1.6.x/server-python/examples/users/create.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/delete-identity.md b/docs/examples/1.6.x/server-python/examples/users/delete-identity.md index 4c78038d11..85c5b6dee3 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete-identity.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete-identity.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/delete-mfa-authenticator.md b/docs/examples/1.6.x/server-python/examples/users/delete-mfa-authenticator.md index c7101d119f..b22d391879 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete-mfa-authenticator.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users from appwrite.enums import AuthenticatorType client = Client() diff --git a/docs/examples/1.6.x/server-python/examples/users/delete-session.md b/docs/examples/1.6.x/server-python/examples/users/delete-session.md index c0fabdb19c..dda5713a9e 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete-session.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete-session.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/delete-sessions.md b/docs/examples/1.6.x/server-python/examples/users/delete-sessions.md index 328a9eeb2f..268c311dd9 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete-sessions.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete-sessions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/delete-target.md b/docs/examples/1.6.x/server-python/examples/users/delete-target.md index 5c2d9df8d8..38cc5a9a23 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete-target.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete-target.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/delete.md b/docs/examples/1.6.x/server-python/examples/users/delete.md index de8b35b513..090c20f5a9 100644 --- a/docs/examples/1.6.x/server-python/examples/users/delete.md +++ b/docs/examples/1.6.x/server-python/examples/users/delete.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/get-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/users/get-mfa-recovery-codes.md index b37739ccae..ec9986ce60 100644 --- a/docs/examples/1.6.x/server-python/examples/users/get-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/users/get-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/get-prefs.md b/docs/examples/1.6.x/server-python/examples/users/get-prefs.md index 23109a9696..eb14d3acb9 100644 --- a/docs/examples/1.6.x/server-python/examples/users/get-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/users/get-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/get-target.md b/docs/examples/1.6.x/server-python/examples/users/get-target.md index d494460c5e..f549f08450 100644 --- a/docs/examples/1.6.x/server-python/examples/users/get-target.md +++ b/docs/examples/1.6.x/server-python/examples/users/get-target.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/get.md b/docs/examples/1.6.x/server-python/examples/users/get.md index d7dda45516..6e018c2b00 100644 --- a/docs/examples/1.6.x/server-python/examples/users/get.md +++ b/docs/examples/1.6.x/server-python/examples/users/get.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-identities.md b/docs/examples/1.6.x/server-python/examples/users/list-identities.md index 7764d74268..b10c320cdd 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-identities.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-identities.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-logs.md b/docs/examples/1.6.x/server-python/examples/users/list-logs.md index d1c6b0abb7..10d8ae0d03 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-logs.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-logs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-memberships.md b/docs/examples/1.6.x/server-python/examples/users/list-memberships.md index 27db71f0c7..fbb3b4c05e 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-memberships.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-memberships.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-mfa-factors.md b/docs/examples/1.6.x/server-python/examples/users/list-mfa-factors.md index 39aed0c173..1f40b1f538 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-mfa-factors.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-mfa-factors.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-sessions.md b/docs/examples/1.6.x/server-python/examples/users/list-sessions.md index fd091b9683..a9eead0d78 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-sessions.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-sessions.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list-targets.md b/docs/examples/1.6.x/server-python/examples/users/list-targets.md index b5b67b96e3..47666467ff 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list-targets.md +++ b/docs/examples/1.6.x/server-python/examples/users/list-targets.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/list.md b/docs/examples/1.6.x/server-python/examples/users/list.md index b191f8ae73..4b09ca5f85 100644 --- a/docs/examples/1.6.x/server-python/examples/users/list.md +++ b/docs/examples/1.6.x/server-python/examples/users/list.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-email-verification.md b/docs/examples/1.6.x/server-python/examples/users/update-email-verification.md index 72ddf7a9bd..4623bc34b1 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-email-verification.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-email-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-email.md b/docs/examples/1.6.x/server-python/examples/users/update-email.md index c977d95250..083715bbfa 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-email.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-email.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-labels.md b/docs/examples/1.6.x/server-python/examples/users/update-labels.md index 04c3999305..24c5b27034 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-labels.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-labels.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-mfa-recovery-codes.md b/docs/examples/1.6.x/server-python/examples/users/update-mfa-recovery-codes.md index ca3b96aa8b..d0e4da4e4a 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-mfa-recovery-codes.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-mfa-recovery-codes.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-mfa.md b/docs/examples/1.6.x/server-python/examples/users/update-mfa.md index e145f9b259..efd6730a26 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-mfa.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-mfa.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-name.md b/docs/examples/1.6.x/server-python/examples/users/update-name.md index d546b95297..6014ef51a5 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-name.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-name.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-password.md b/docs/examples/1.6.x/server-python/examples/users/update-password.md index 0c7e7bf030..90ac15f565 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-password.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-password.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-phone-verification.md b/docs/examples/1.6.x/server-python/examples/users/update-phone-verification.md index b13c4fba33..a62e6a8ceb 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-phone-verification.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-phone-verification.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-phone.md b/docs/examples/1.6.x/server-python/examples/users/update-phone.md index ecb01728e8..f522730003 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-phone.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-phone.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-prefs.md b/docs/examples/1.6.x/server-python/examples/users/update-prefs.md index ca6999c950..64d9df39f8 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-prefs.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-prefs.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-status.md b/docs/examples/1.6.x/server-python/examples/users/update-status.md index ebec495c33..8943ef59f5 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-status.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-status.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-python/examples/users/update-target.md b/docs/examples/1.6.x/server-python/examples/users/update-target.md index f9bdfb43ef..89513850b0 100644 --- a/docs/examples/1.6.x/server-python/examples/users/update-target.md +++ b/docs/examples/1.6.x/server-python/examples/users/update-target.md @@ -1,4 +1,5 @@ from appwrite.client import Client +from appwrite.services.users import Users client = Client() client.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md index 197ea2767d..71a5302e1a 100644 --- a/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-rest/examples/databases/update-string-attribute.md @@ -8,6 +8,6 @@ X-Appwrite-Key: <YOUR_API_KEY> { "required": false, "default": "<DEFAULT>", - "size": 0, + "size": 1, "newKey": } diff --git a/docs/examples/1.6.x/server-rest/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-rest/examples/functions/download-deployment.md deleted file mode 100644 index ccd37283c9..0000000000 --- a/docs/examples/1.6.x/server-rest/examples/functions/download-deployment.md +++ /dev/null @@ -1,7 +0,0 @@ -GET /v1/functions/{functionId}/deployments/{deploymentId}/download HTTP/1.1 -Host: cloud.appwrite.io -Content-Type: application/json -X-Appwrite-Response-Format: 1.5.0 -X-Appwrite-Project: <YOUR_PROJECT_ID> -X-Appwrite-Key: <YOUR_API_KEY> - diff --git a/docs/examples/1.6.x/server-rest/examples/functions/get-template.md b/docs/examples/1.6.x/server-rest/examples/functions/get-template.md deleted file mode 100644 index d4e1f95cf5..0000000000 --- a/docs/examples/1.6.x/server-rest/examples/functions/get-template.md +++ /dev/null @@ -1,6 +0,0 @@ -GET /v1/functions/templates/{templateId} HTTP/1.1 -Host: cloud.appwrite.io -Content-Type: application/json -X-Appwrite-Response-Format: 1.6.0 -X-Appwrite-Project: <YOUR_PROJECT_ID> - diff --git a/docs/examples/1.6.x/server-rest/examples/functions/list-templates.md b/docs/examples/1.6.x/server-rest/examples/functions/list-templates.md deleted file mode 100644 index b671bedebf..0000000000 --- a/docs/examples/1.6.x/server-rest/examples/functions/list-templates.md +++ /dev/null @@ -1,6 +0,0 @@ -GET /v1/functions/templates HTTP/1.1 -Host: cloud.appwrite.io -Content-Type: application/json -X-Appwrite-Response-Format: 1.6.0 -X-Appwrite-Project: <YOUR_PROJECT_ID> - diff --git a/docs/examples/1.6.x/server-rest/examples/messaging/create-push.md b/docs/examples/1.6.x/server-rest/examples/messaging/create-push.md index 1c7550950b..cf5256d921 100644 --- a/docs/examples/1.6.x/server-rest/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-rest/examples/messaging/create-push.md @@ -19,7 +19,10 @@ X-Appwrite-Key: <YOUR_API_KEY> "sound": "<SOUND>", "color": "<COLOR>", "tag": "<TAG>", - "badge": "<BADGE>", + "badge": 0, "draft": false, - "scheduledAt": + "scheduledAt": , + "contentAvailable": false, + "critical": false, + "priority": "normal" } diff --git a/docs/examples/1.6.x/server-rest/examples/messaging/update-push.md b/docs/examples/1.6.x/server-rest/examples/messaging/update-push.md index 7a0338c74b..2159bc8aa2 100644 --- a/docs/examples/1.6.x/server-rest/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-rest/examples/messaging/update-push.md @@ -20,5 +20,8 @@ X-Appwrite-Key: <YOUR_API_KEY> "tag": "<TAG>", "badge": 0, "draft": false, - "scheduledAt": + "scheduledAt": , + "contentAvailable": false, + "critical": false, + "priority": "normal" } diff --git a/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md index 3b3c5eb644..5e4ac573dc 100644 --- a/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-ruby/examples/databases/update-string-attribute.md @@ -15,6 +15,6 @@ result = databases.update_string_attribute( key: '', required: false, default: '<DEFAULT>', - size: null, # optional + size: 1, # optional new_key: '' # optional ) diff --git a/docs/examples/1.6.x/server-ruby/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-ruby/examples/functions/download-deployment.md deleted file mode 100644 index 748d0c9d01..0000000000 --- a/docs/examples/1.6.x/server-ruby/examples/functions/download-deployment.md +++ /dev/null @@ -1,15 +0,0 @@ -require 'appwrite' - -include Appwrite - -client = Client.new - .set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint - .set_project('<YOUR_PROJECT_ID>') # Your project ID - .set_key('<YOUR_API_KEY>') # Your secret API key - -functions = Functions.new(client) - -result = functions.download_deployment( - function_id: '<FUNCTION_ID>', - deployment_id: '<DEPLOYMENT_ID>' -) diff --git a/docs/examples/1.6.x/server-ruby/examples/functions/get-template.md b/docs/examples/1.6.x/server-ruby/examples/functions/get-template.md deleted file mode 100644 index 5274880f67..0000000000 --- a/docs/examples/1.6.x/server-ruby/examples/functions/get-template.md +++ /dev/null @@ -1,13 +0,0 @@ -require 'appwrite' - -include Appwrite - -client = Client.new - .set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint - .set_project('<YOUR_PROJECT_ID>') # Your project ID - -functions = Functions.new(client) - -result = functions.get_template( - template_id: '<TEMPLATE_ID>' -) diff --git a/docs/examples/1.6.x/server-ruby/examples/functions/list-templates.md b/docs/examples/1.6.x/server-ruby/examples/functions/list-templates.md deleted file mode 100644 index 8bee6b0187..0000000000 --- a/docs/examples/1.6.x/server-ruby/examples/functions/list-templates.md +++ /dev/null @@ -1,16 +0,0 @@ -require 'appwrite' - -include Appwrite - -client = Client.new - .set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint - .set_project('<YOUR_PROJECT_ID>') # Your project ID - -functions = Functions.new(client) - -result = functions.list_templates( - runtimes: [], # optional - use_cases: [], # optional - limit: 1, # optional - offset: 0 # optional -) diff --git a/docs/examples/1.6.x/server-ruby/examples/messaging/create-push.md b/docs/examples/1.6.x/server-ruby/examples/messaging/create-push.md index 1c6700db43..61663f4dc0 100644 --- a/docs/examples/1.6.x/server-ruby/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-ruby/examples/messaging/create-push.md @@ -11,8 +11,8 @@ messaging = Messaging.new(client) result = messaging.create_push( message_id: '<MESSAGE_ID>', - title: '<TITLE>', - body: '<BODY>', + title: '<TITLE>', # optional + body: '<BODY>', # optional topics: [], # optional users: [], # optional targets: [], # optional @@ -23,7 +23,10 @@ result = messaging.create_push( sound: '<SOUND>', # optional color: '<COLOR>', # optional tag: '<TAG>', # optional - badge: '<BADGE>', # optional + badge: null, # optional draft: false, # optional - scheduled_at: '' # optional + scheduled_at: '', # optional + content_available: false, # optional + critical: false, # optional + priority: MessagePriority::NORMAL # optional ) diff --git a/docs/examples/1.6.x/server-ruby/examples/messaging/update-push.md b/docs/examples/1.6.x/server-ruby/examples/messaging/update-push.md index 54f6368eee..6bf9fcaa79 100644 --- a/docs/examples/1.6.x/server-ruby/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-ruby/examples/messaging/update-push.md @@ -25,5 +25,8 @@ result = messaging.update_push( tag: '<TAG>', # optional badge: null, # optional draft: false, # optional - scheduled_at: '' # optional + scheduled_at: '', # optional + content_available: false, # optional + critical: false, # optional + priority: MessagePriority::NORMAL # optional ) diff --git a/docs/examples/1.6.x/server-swift/examples/account/update-mfa-challenge.md b/docs/examples/1.6.x/server-swift/examples/account/update-mfa-challenge.md index eed3bfade7..fee76bf0dd 100644 --- a/docs/examples/1.6.x/server-swift/examples/account/update-mfa-challenge.md +++ b/docs/examples/1.6.x/server-swift/examples/account/update-mfa-challenge.md @@ -7,7 +7,7 @@ let client = Client() let account = Account(client) -let result = try await account.updateMfaChallenge( +let session = try await account.updateMfaChallenge( challengeId: "<CHALLENGE_ID>", otp: "<OTP>" ) diff --git a/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md b/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md index 5fafd5e72e..d3129dcce2 100644 --- a/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md +++ b/docs/examples/1.6.x/server-swift/examples/databases/update-string-attribute.md @@ -13,7 +13,7 @@ let attributeString = try await databases.updateStringAttribute( key: "", required: false, default: "<DEFAULT>", - size: 0, // optional + size: 1, // optional newKey: "" // optional ) diff --git a/docs/examples/1.6.x/server-swift/examples/functions/download-deployment.md b/docs/examples/1.6.x/server-swift/examples/functions/download-deployment.md deleted file mode 100644 index 753d7058e6..0000000000 --- a/docs/examples/1.6.x/server-swift/examples/functions/download-deployment.md +++ /dev/null @@ -1,14 +0,0 @@ -import Appwrite - -let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("<YOUR_PROJECT_ID>") // Your project ID - .setKey("<YOUR_API_KEY>") // Your secret API key - -let functions = Functions(client) - -let bytes = try await functions.downloadDeployment( - functionId: "<FUNCTION_ID>", - deploymentId: "<DEPLOYMENT_ID>" -) - diff --git a/docs/examples/1.6.x/server-swift/examples/functions/get-template.md b/docs/examples/1.6.x/server-swift/examples/functions/get-template.md deleted file mode 100644 index bc7a9a3aef..0000000000 --- a/docs/examples/1.6.x/server-swift/examples/functions/get-template.md +++ /dev/null @@ -1,12 +0,0 @@ -import Appwrite - -let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("<YOUR_PROJECT_ID>") // Your project ID - -let functions = Functions(client) - -let templateFunction = try await functions.getTemplate( - templateId: "<TEMPLATE_ID>" -) - diff --git a/docs/examples/1.6.x/server-swift/examples/functions/list-templates.md b/docs/examples/1.6.x/server-swift/examples/functions/list-templates.md deleted file mode 100644 index d0090ab803..0000000000 --- a/docs/examples/1.6.x/server-swift/examples/functions/list-templates.md +++ /dev/null @@ -1,15 +0,0 @@ -import Appwrite - -let client = Client() - .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint - .setProject("<YOUR_PROJECT_ID>") // Your project ID - -let functions = Functions(client) - -let templateFunctionList = try await functions.listTemplates( - runtimes: [], // optional - useCases: [], // optional - limit: 1, // optional - offset: 0 // optional -) - diff --git a/docs/examples/1.6.x/server-swift/examples/messaging/create-push.md b/docs/examples/1.6.x/server-swift/examples/messaging/create-push.md index dbc7bf0ca6..42f48ddd2e 100644 --- a/docs/examples/1.6.x/server-swift/examples/messaging/create-push.md +++ b/docs/examples/1.6.x/server-swift/examples/messaging/create-push.md @@ -1,4 +1,5 @@ import Appwrite +import AppwriteEnums let client = Client() .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint @@ -9,8 +10,8 @@ let messaging = Messaging(client) let message = try await messaging.createPush( messageId: "<MESSAGE_ID>", - title: "<TITLE>", - body: "<BODY>", + title: "<TITLE>", // optional + body: "<BODY>", // optional topics: [], // optional users: [], // optional targets: [], // optional @@ -21,8 +22,11 @@ let message = try await messaging.createPush( sound: "<SOUND>", // optional color: "<COLOR>", // optional tag: "<TAG>", // optional - badge: "<BADGE>", // optional + badge: 0, // optional draft: false, // optional - scheduledAt: "" // optional + scheduledAt: "", // optional + contentAvailable: false, // optional + critical: false, // optional + priority: .normal // optional ) diff --git a/docs/examples/1.6.x/server-swift/examples/messaging/update-push.md b/docs/examples/1.6.x/server-swift/examples/messaging/update-push.md index 40ce34bf66..02893a180a 100644 --- a/docs/examples/1.6.x/server-swift/examples/messaging/update-push.md +++ b/docs/examples/1.6.x/server-swift/examples/messaging/update-push.md @@ -1,4 +1,5 @@ import Appwrite +import AppwriteEnums let client = Client() .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint @@ -23,6 +24,9 @@ let message = try await messaging.updatePush( tag: "<TAG>", // optional badge: 0, // optional draft: false, // optional - scheduledAt: "" // optional + scheduledAt: "", // optional + contentAvailable: false, // optional + critical: false, // optional + priority: .normal // optional ) diff --git a/docs/examples/1.6.x/server-swift/examples/users/delete-mfa-authenticator.md b/docs/examples/1.6.x/server-swift/examples/users/delete-mfa-authenticator.md index 902d0c904c..5f1d6a0eeb 100644 --- a/docs/examples/1.6.x/server-swift/examples/users/delete-mfa-authenticator.md +++ b/docs/examples/1.6.x/server-swift/examples/users/delete-mfa-authenticator.md @@ -8,7 +8,7 @@ let client = Client() let users = Users(client) -let user = try await users.deleteMfaAuthenticator( +let result = try await users.deleteMfaAuthenticator( userId: "<USER_ID>", type: .totp ) diff --git a/docs/references/account/create-push-target.md b/docs/references/account/create-push-target.md new file mode 100644 index 0000000000..c54f180638 --- /dev/null +++ b/docs/references/account/create-push-target.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/account/delete-push-target.md b/docs/references/account/delete-push-target.md new file mode 100644 index 0000000000..5909a37b27 --- /dev/null +++ b/docs/references/account/delete-push-target.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/account/update-push-target.md b/docs/references/account/update-push-target.md new file mode 100644 index 0000000000..997ffaafea --- /dev/null +++ b/docs/references/account/update-push-target.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/assistant/chat.md b/docs/references/assistant/chat.md new file mode 100644 index 0000000000..5297d1c195 --- /dev/null +++ b/docs/references/assistant/chat.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/databases/create-document.md b/docs/references/databases/create-document.md index a2444d58a4..643518df51 100644 --- a/docs/references/databases/create-document.md +++ b/docs/references/databases/create-document.md @@ -1 +1 @@ -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. \ No newline at end of file +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. diff --git a/docs/references/databases/get-collection-usage.md b/docs/references/databases/get-collection-usage.md new file mode 100644 index 0000000000..48682a075f --- /dev/null +++ b/docs/references/databases/get-collection-usage.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/databases/get-database-usage.md b/docs/references/databases/get-database-usage.md new file mode 100644 index 0000000000..2c2628a464 --- /dev/null +++ b/docs/references/databases/get-database-usage.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/databases/get-usage.md b/docs/references/databases/get-usage.md new file mode 100644 index 0000000000..d41f8704c8 --- /dev/null +++ b/docs/references/databases/get-usage.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/functions/create-build.md b/docs/references/functions/create-build.md new file mode 100644 index 0000000000..160a04c291 --- /dev/null +++ b/docs/references/functions/create-build.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/functions/get-function-usage.md b/docs/references/functions/get-function-usage.md new file mode 100644 index 0000000000..4498abb05b --- /dev/null +++ b/docs/references/functions/get-function-usage.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/functions/get-functions-usage.md b/docs/references/functions/get-functions-usage.md new file mode 100644 index 0000000000..14427d335d --- /dev/null +++ b/docs/references/functions/get-functions-usage.md @@ -0,0 +1 @@ +Get usage metrics and statistics for a for all functions. View statistics including total functions, 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. \ No newline at end of file diff --git a/docs/references/functions/list-deployments.md b/docs/references/functions/list-deployments.md index 8b24f911f2..80bbba1bf6 100644 --- a/docs/references/functions/list-deployments.md +++ b/docs/references/functions/list-deployments.md @@ -1 +1 @@ -Get a list of all the project's code deployments. You can use the query params to filter your results. \ No newline at end of file +Get a list of all the function's code deployments. You can use the query params to filter your results. \ No newline at end of file diff --git a/docs/references/functions/update-deployment-build.md b/docs/references/functions/update-deployment-build.md new file mode 100644 index 0000000000..d047990adf --- /dev/null +++ b/docs/references/functions/update-deployment-build.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/health/get-queue-stats-resources.md b/docs/references/health/get-queue-stats-resources.md new file mode 100644 index 0000000000..5221327467 --- /dev/null +++ b/docs/references/health/get-queue-stats-resources.md @@ -0,0 +1 @@ +Get the number of metrics that are waiting to be processed in the Appwrite stats resources queue. \ No newline at end of file diff --git a/docs/references/health/get-queue-usage-dump.md b/docs/references/health/get-queue-stats-usage-dump.md similarity index 100% rename from docs/references/health/get-queue-usage-dump.md rename to docs/references/health/get-queue-stats-usage-dump.md diff --git a/docs/references/health/get-queue-usage.md b/docs/references/health/get-queue-stats-usage.md similarity index 100% rename from docs/references/health/get-queue-usage.md rename to docs/references/health/get-queue-stats-usage.md diff --git a/docs/references/messaging/update-email.md b/docs/references/messaging/update-email.md index 89f01d7a11..1f0d4b61a4 100644 --- a/docs/references/messaging/update-email.md +++ b/docs/references/messaging/update-email.md @@ -1 +1 @@ -Update an email message by its unique ID. +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. diff --git a/docs/references/messaging/update-push.md b/docs/references/messaging/update-push.md index dd200a9729..e84187116d 100644 --- a/docs/references/messaging/update-push.md +++ b/docs/references/messaging/update-push.md @@ -1 +1 @@ -Update a push notification by its unique ID. +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. diff --git a/docs/references/messaging/update-sms.md b/docs/references/messaging/update-sms.md index 2f9b57a7a7..5a1cb3d67f 100644 --- a/docs/references/messaging/update-sms.md +++ b/docs/references/messaging/update-sms.md @@ -1 +1 @@ -Update an SMS message by its unique ID. +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. diff --git a/docs/references/migrations/delete-migration.md b/docs/references/migrations/delete-migration.md new file mode 100644 index 0000000000..9d361ac693 --- /dev/null +++ b/docs/references/migrations/delete-migration.md @@ -0,0 +1 @@ +Delete a migration by its unique ID. This endpoint allows you to remove a migration from your project's migration history. \ No newline at end of file diff --git a/docs/references/migrations/get-migration.md b/docs/references/migrations/get-migration.md new file mode 100644 index 0000000000..710bef6863 --- /dev/null +++ b/docs/references/migrations/get-migration.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/list-migrations.md b/docs/references/migrations/list-migrations.md new file mode 100644 index 0000000000..b1acb3f7b3 --- /dev/null +++ b/docs/references/migrations/list-migrations.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/migration-appwrite-report.md b/docs/references/migrations/migration-appwrite-report.md new file mode 100644 index 0000000000..69d556f5f3 --- /dev/null +++ b/docs/references/migrations/migration-appwrite-report.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/migration-appwrite.md b/docs/references/migrations/migration-appwrite.md new file mode 100644 index 0000000000..12ee742387 --- /dev/null +++ b/docs/references/migrations/migration-appwrite.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/migration-csv.md b/docs/references/migrations/migration-csv.md new file mode 100644 index 0000000000..7a32d5ff6e --- /dev/null +++ b/docs/references/migrations/migration-csv.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/migration-firebase-report.md b/docs/references/migrations/migration-firebase-report.md new file mode 100644 index 0000000000..af27587331 --- /dev/null +++ b/docs/references/migrations/migration-firebase-report.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/migration-firebase.md b/docs/references/migrations/migration-firebase.md new file mode 100644 index 0000000000..3a7f620a7c --- /dev/null +++ b/docs/references/migrations/migration-firebase.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/migration-nhost-report.md b/docs/references/migrations/migration-nhost-report.md new file mode 100644 index 0000000000..895da51464 --- /dev/null +++ b/docs/references/migrations/migration-nhost-report.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/migration-nhost.md b/docs/references/migrations/migration-nhost.md new file mode 100644 index 0000000000..b7a727dd2b --- /dev/null +++ b/docs/references/migrations/migration-nhost.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/migration-supabase-report.md b/docs/references/migrations/migration-supabase-report.md new file mode 100644 index 0000000000..d9636b5f1d --- /dev/null +++ b/docs/references/migrations/migration-supabase-report.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/migration-supabase.md b/docs/references/migrations/migration-supabase.md new file mode 100644 index 0000000000..34bbb1eece --- /dev/null +++ b/docs/references/migrations/migration-supabase.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/migrations/retry-migration.md b/docs/references/migrations/retry-migration.md new file mode 100644 index 0000000000..49b80ad6d4 --- /dev/null +++ b/docs/references/migrations/retry-migration.md @@ -0,0 +1 @@ +Retry a failed migration. This endpoint allows you to retry a migration that has previously failed. \ No newline at end of file diff --git a/docs/references/project/get-usage.md b/docs/references/project/get-usage.md new file mode 100644 index 0000000000..d6802c5588 --- /dev/null +++ b/docs/references/project/get-usage.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/projects/create-jwt.md b/docs/references/projects/create-jwt.md new file mode 100644 index 0000000000..9a6f8ebf6b --- /dev/null +++ b/docs/references/projects/create-jwt.md @@ -0,0 +1 @@ +Create a new JWT token. This token can be used to authenticate users with custom scopes and expiration time. \ No newline at end of file diff --git a/docs/references/projects/create-key.md b/docs/references/projects/create-key.md new file mode 100644 index 0000000000..d6633d936d --- /dev/null +++ b/docs/references/projects/create-key.md @@ -0,0 +1 @@ +Create a new API key. It's recommended to have multiple API keys with strict scopes for separate functions within your project. \ No newline at end of file diff --git a/docs/references/projects/create-platform.md b/docs/references/projects/create-platform.md new file mode 100644 index 0000000000..b5d8be0ff9 --- /dev/null +++ b/docs/references/projects/create-platform.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/projects/create-smtp-test.md b/docs/references/projects/create-smtp-test.md new file mode 100644 index 0000000000..63cea9d21f --- /dev/null +++ b/docs/references/projects/create-smtp-test.md @@ -0,0 +1 @@ +Send a test email to verify SMTP configuration. \ No newline at end of file diff --git a/docs/references/projects/create-webhook.md b/docs/references/projects/create-webhook.md new file mode 100644 index 0000000000..cd0e93332b --- /dev/null +++ b/docs/references/projects/create-webhook.md @@ -0,0 +1 @@ +Create a new webhook. Use this endpoint to configure a URL that will receive events from Appwrite when specific events occur. \ No newline at end of file diff --git a/docs/references/projects/create.md b/docs/references/projects/create.md new file mode 100644 index 0000000000..d502c269ef --- /dev/null +++ b/docs/references/projects/create.md @@ -0,0 +1 @@ +Create a new project. You can create a maximum of 100 projects per account. \ No newline at end of file diff --git a/docs/references/projects/delete-email-template.md b/docs/references/projects/delete-email-template.md new file mode 100644 index 0000000000..332b1d6117 --- /dev/null +++ b/docs/references/projects/delete-email-template.md @@ -0,0 +1 @@ +Reset a custom email template to its default value. This endpoint removes any custom content and restores the template to its original state. \ No newline at end of file diff --git a/docs/references/projects/delete-key.md b/docs/references/projects/delete-key.md new file mode 100644 index 0000000000..9f3774b419 --- /dev/null +++ b/docs/references/projects/delete-key.md @@ -0,0 +1 @@ +Delete a key by its unique ID. Once deleted, the key can no longer be used to authenticate API calls. \ No newline at end of file diff --git a/docs/references/projects/delete-platform.md b/docs/references/projects/delete-platform.md new file mode 100644 index 0000000000..7d538cac26 --- /dev/null +++ b/docs/references/projects/delete-platform.md @@ -0,0 +1 @@ +Delete a platform by its unique ID. This endpoint removes the platform and all its configurations from the project. \ No newline at end of file diff --git a/docs/references/projects/delete-sms-template.md b/docs/references/projects/delete-sms-template.md new file mode 100644 index 0000000000..c5a7e6cac9 --- /dev/null +++ b/docs/references/projects/delete-sms-template.md @@ -0,0 +1 @@ +Reset a custom SMS template to its default value. This endpoint removes any custom message and restores the template to its original state. \ No newline at end of file diff --git a/docs/references/projects/delete-webhook.md b/docs/references/projects/delete-webhook.md new file mode 100644 index 0000000000..74fee2bcec --- /dev/null +++ b/docs/references/projects/delete-webhook.md @@ -0,0 +1 @@ +Delete a webhook by its unique ID. Once deleted, the webhook will no longer receive project events. \ No newline at end of file diff --git a/docs/references/projects/delete.md b/docs/references/projects/delete.md new file mode 100644 index 0000000000..4a8070c082 --- /dev/null +++ b/docs/references/projects/delete.md @@ -0,0 +1 @@ +Delete a project by its unique ID. \ No newline at end of file diff --git a/docs/references/projects/get-email-template.md b/docs/references/projects/get-email-template.md new file mode 100644 index 0000000000..6119a0a183 --- /dev/null +++ b/docs/references/projects/get-email-template.md @@ -0,0 +1 @@ +Get a custom email template for the specified locale and type. This endpoint returns the template content, subject, and other configuration details. \ No newline at end of file diff --git a/docs/references/projects/get-key.md b/docs/references/projects/get-key.md new file mode 100644 index 0000000000..bd6351f420 --- /dev/null +++ b/docs/references/projects/get-key.md @@ -0,0 +1 @@ +Get a key by its unique ID. This endpoint returns details about a specific API key in your project including it's scopes. \ No newline at end of file diff --git a/docs/references/projects/get-platform.md b/docs/references/projects/get-platform.md new file mode 100644 index 0000000000..87129b829d --- /dev/null +++ b/docs/references/projects/get-platform.md @@ -0,0 +1 @@ +Get a platform by its unique ID. This endpoint returns the platform's details, including its name, type, and key configurations. \ No newline at end of file diff --git a/docs/references/projects/get-sms-template.md b/docs/references/projects/get-sms-template.md new file mode 100644 index 0000000000..6ef1d93029 --- /dev/null +++ b/docs/references/projects/get-sms-template.md @@ -0,0 +1 @@ +Get a custom SMS template for the specified locale and type returning it's contents. \ No newline at end of file diff --git a/docs/references/projects/get-webhook.md b/docs/references/projects/get-webhook.md new file mode 100644 index 0000000000..559c73c748 --- /dev/null +++ b/docs/references/projects/get-webhook.md @@ -0,0 +1 @@ +Get a webhook by its unique ID. This endpoint returns details about a specific webhook configured for a project. \ No newline at end of file diff --git a/docs/references/projects/get.md b/docs/references/projects/get.md new file mode 100644 index 0000000000..b7a1165adc --- /dev/null +++ b/docs/references/projects/get.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/projects/list-keys.md b/docs/references/projects/list-keys.md new file mode 100644 index 0000000000..a7b701b0d7 --- /dev/null +++ b/docs/references/projects/list-keys.md @@ -0,0 +1 @@ +Get a list of all API keys from the current project. \ No newline at end of file diff --git a/docs/references/projects/list-platforms.md b/docs/references/projects/list-platforms.md new file mode 100644 index 0000000000..ed9ade0852 --- /dev/null +++ b/docs/references/projects/list-platforms.md @@ -0,0 +1 @@ +Get a list of all platforms in the project. This endpoint returns an array of all platforms and their configurations. \ No newline at end of file diff --git a/docs/references/projects/list-webhooks.md b/docs/references/projects/list-webhooks.md new file mode 100644 index 0000000000..bbbf4c7376 --- /dev/null +++ b/docs/references/projects/list-webhooks.md @@ -0,0 +1 @@ +Get a list of all webhooks belonging to the project. You can use the query params to filter your results. \ No newline at end of file diff --git a/docs/references/projects/list.md b/docs/references/projects/list.md new file mode 100644 index 0000000000..576a4b79ae --- /dev/null +++ b/docs/references/projects/list.md @@ -0,0 +1 @@ +Get a list of all projects. You can use the query params to filter your results. \ No newline at end of file diff --git a/docs/references/projects/update-api-status-all.md b/docs/references/projects/update-api-status-all.md new file mode 100644 index 0000000000..654070759f --- /dev/null +++ b/docs/references/projects/update-api-status-all.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/projects/update-api-status.md b/docs/references/projects/update-api-status.md new file mode 100644 index 0000000000..af10a0d4f4 --- /dev/null +++ b/docs/references/projects/update-api-status.md @@ -0,0 +1 @@ +Update the status of a specific API type. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime. \ No newline at end of file diff --git a/docs/references/projects/update-auth-duration.md b/docs/references/projects/update-auth-duration.md new file mode 100644 index 0000000000..bdc75fa6f0 --- /dev/null +++ b/docs/references/projects/update-auth-duration.md @@ -0,0 +1 @@ +Update how long sessions created within a project should stay active for. \ No newline at end of file diff --git a/docs/references/projects/update-auth-limit.md b/docs/references/projects/update-auth-limit.md new file mode 100644 index 0000000000..c8faa3fe37 --- /dev/null +++ b/docs/references/projects/update-auth-limit.md @@ -0,0 +1 @@ +Update the maximum number of users allowed in this project. Set to 0 for unlimited users. \ No newline at end of file diff --git a/docs/references/projects/update-auth-password-dictionary.md b/docs/references/projects/update-auth-password-dictionary.md new file mode 100644 index 0000000000..1d47d30bb5 --- /dev/null +++ b/docs/references/projects/update-auth-password-dictionary.md @@ -0,0 +1 @@ +Enable or disable checking user passwords against common passwords dictionary. This helps ensure users don't use common and insecure passwords. \ No newline at end of file diff --git a/docs/references/projects/update-auth-password-history.md b/docs/references/projects/update-auth-password-history.md new file mode 100644 index 0000000000..3a892915d5 --- /dev/null +++ b/docs/references/projects/update-auth-password-history.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/projects/update-auth-sessions-limit.md b/docs/references/projects/update-auth-sessions-limit.md new file mode 100644 index 0000000000..7d5fdffae7 --- /dev/null +++ b/docs/references/projects/update-auth-sessions-limit.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/projects/update-auth-status.md b/docs/references/projects/update-auth-status.md new file mode 100644 index 0000000000..5d39ec29c4 --- /dev/null +++ b/docs/references/projects/update-auth-status.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/projects/update-email-template.md b/docs/references/projects/update-email-template.md new file mode 100644 index 0000000000..d2bf124541 --- /dev/null +++ b/docs/references/projects/update-email-template.md @@ -0,0 +1 @@ +Update a custom email template for the specified locale and type. Use this endpoint to modify the content of your email templates. \ No newline at end of file diff --git a/docs/references/projects/update-key.md b/docs/references/projects/update-key.md new file mode 100644 index 0000000000..4934a51497 --- /dev/null +++ b/docs/references/projects/update-key.md @@ -0,0 +1 @@ +Update a key by its unique ID. Use this endpoint to update the name, scopes, or expiration time of an API key. \ No newline at end of file diff --git a/docs/references/projects/update-memberships-privacy.md b/docs/references/projects/update-memberships-privacy.md new file mode 100644 index 0000000000..a1affc1166 --- /dev/null +++ b/docs/references/projects/update-memberships-privacy.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/projects/update-mock-numbers.md b/docs/references/projects/update-mock-numbers.md new file mode 100644 index 0000000000..7fa92455c1 --- /dev/null +++ b/docs/references/projects/update-mock-numbers.md @@ -0,0 +1 @@ +Update the list of mock phone numbers for testing. Use these numbers to bypass SMS verification in development. \ No newline at end of file diff --git a/docs/references/projects/update-oauth2.md b/docs/references/projects/update-oauth2.md new file mode 100644 index 0000000000..2285135991 --- /dev/null +++ b/docs/references/projects/update-oauth2.md @@ -0,0 +1 @@ +Update the OAuth2 provider configurations. Use this endpoint to set up or update the OAuth2 provider credentials or enable/disable providers. \ No newline at end of file diff --git a/docs/references/projects/update-personal-data-check.md b/docs/references/projects/update-personal-data-check.md new file mode 100644 index 0000000000..42847fdbfc --- /dev/null +++ b/docs/references/projects/update-personal-data-check.md @@ -0,0 +1 @@ +Enable or disable checking user passwords against their personal data. This helps prevent users from using personal information in their passwords. \ No newline at end of file diff --git a/docs/references/projects/update-platform.md b/docs/references/projects/update-platform.md new file mode 100644 index 0000000000..d04b07bafd --- /dev/null +++ b/docs/references/projects/update-platform.md @@ -0,0 +1 @@ +Update a platform by its unique ID. Use this endpoint to update the platform's name, key, platform store ID, or hostname. \ No newline at end of file diff --git a/docs/references/projects/update-service-status-all.md b/docs/references/projects/update-service-status-all.md new file mode 100644 index 0000000000..f05e7d8c5c --- /dev/null +++ b/docs/references/projects/update-service-status-all.md @@ -0,0 +1 @@ +Update the status of all services. Use this endpoint to enable or disable all optional services at once. \ No newline at end of file diff --git a/docs/references/projects/update-service-status.md b/docs/references/projects/update-service-status.md new file mode 100644 index 0000000000..9d3b0743a8 --- /dev/null +++ b/docs/references/projects/update-service-status.md @@ -0,0 +1 @@ +Update the status of a specific service. Use this endpoint to enable or disable a service in your project. \ No newline at end of file diff --git a/docs/references/projects/update-session-alerts.md b/docs/references/projects/update-session-alerts.md new file mode 100644 index 0000000000..36859e0c1e --- /dev/null +++ b/docs/references/projects/update-session-alerts.md @@ -0,0 +1 @@ +Enable or disable session email alerts. When enabled, users will receive email notifications when new sessions are created. \ No newline at end of file diff --git a/docs/references/projects/update-sms-template.md b/docs/references/projects/update-sms-template.md new file mode 100644 index 0000000000..3e67f613b7 --- /dev/null +++ b/docs/references/projects/update-sms-template.md @@ -0,0 +1 @@ +Update a custom SMS template for the specified locale and type. Use this endpoint to modify the content of your SMS templates. \ No newline at end of file diff --git a/docs/references/projects/update-smtp.md b/docs/references/projects/update-smtp.md new file mode 100644 index 0000000000..7d898e1ed1 --- /dev/null +++ b/docs/references/projects/update-smtp.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/projects/update-team.md b/docs/references/projects/update-team.md new file mode 100644 index 0000000000..fb02eda88c --- /dev/null +++ b/docs/references/projects/update-team.md @@ -0,0 +1 @@ +Update the team ID of a project allowing for it to be transferred to another team. \ No newline at end of file diff --git a/docs/references/projects/update-webhook-signature.md b/docs/references/projects/update-webhook-signature.md new file mode 100644 index 0000000000..8525a05777 --- /dev/null +++ b/docs/references/projects/update-webhook-signature.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/projects/update-webhook.md b/docs/references/projects/update-webhook.md new file mode 100644 index 0000000000..745e4aebe1 --- /dev/null +++ b/docs/references/projects/update-webhook.md @@ -0,0 +1 @@ +Update a webhook by its unique ID. Use this endpoint to update the URL, events, or status of an existing webhook. \ No newline at end of file diff --git a/docs/references/projects/update.md b/docs/references/projects/update.md new file mode 100644 index 0000000000..60c072c477 --- /dev/null +++ b/docs/references/projects/update.md @@ -0,0 +1 @@ +Update a project by its unique ID. \ No newline at end of file diff --git a/docs/references/proxy/create-rule.md b/docs/references/proxy/create-rule.md deleted file mode 100644 index be567b1cc0..0000000000 --- a/docs/references/proxy/create-rule.md +++ /dev/null @@ -1 +0,0 @@ -Create a new proxy rule. \ No newline at end of file diff --git a/docs/references/proxy/update-rule-verification.md b/docs/references/proxy/update-rule-verification.md new file mode 100644 index 0000000000..c06994bc59 --- /dev/null +++ b/docs/references/proxy/update-rule-verification.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/storage/get-bucket-usage.md b/docs/references/storage/get-bucket-usage.md new file mode 100644 index 0000000000..98e9867831 --- /dev/null +++ b/docs/references/storage/get-bucket-usage.md @@ -0,0 +1 @@ +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. diff --git a/docs/references/storage/get-usage.md b/docs/references/storage/get-usage.md new file mode 100644 index 0000000000..697c680001 --- /dev/null +++ b/docs/references/storage/get-usage.md @@ -0,0 +1 @@ +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. diff --git a/docs/references/users/get-usage.md b/docs/references/users/get-usage.md new file mode 100644 index 0000000000..2a9379c847 --- /dev/null +++ b/docs/references/users/get-usage.md @@ -0,0 +1 @@ +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. diff --git a/docs/references/vcs/create-github-installation.md b/docs/references/vcs/create-github-installation.md new file mode 100644 index 0000000000..60873faf6d --- /dev/null +++ b/docs/references/vcs/create-github-installation.md @@ -0,0 +1 @@ +Begin Appwrite's GitHub's app installation to set up version control integration. This endpoint responds with a redirect URL to the GitHub App's installation page. The GitHub App must be configured in your environment for this endpoint to work. \ No newline at end of file diff --git a/docs/references/vcs/create-repository-detection.md b/docs/references/vcs/create-repository-detection.md new file mode 100644 index 0000000000..d031cdc746 --- /dev/null +++ b/docs/references/vcs/create-repository-detection.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/vcs/create-repository.md b/docs/references/vcs/create-repository.md new file mode 100644 index 0000000000..771265bd01 --- /dev/null +++ b/docs/references/vcs/create-repository.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/vcs/delete-installation.md b/docs/references/vcs/delete-installation.md new file mode 100644 index 0000000000..1f07de364d --- /dev/null +++ b/docs/references/vcs/delete-installation.md @@ -0,0 +1 @@ +Delete a VCS installation by its unique ID. This endpoint removes the installation and all its associated repositories from the project. \ No newline at end of file diff --git a/docs/references/vcs/get-installation.md b/docs/references/vcs/get-installation.md new file mode 100644 index 0000000000..0679d9a0e9 --- /dev/null +++ b/docs/references/vcs/get-installation.md @@ -0,0 +1 @@ +Get a VCS installation by its unique ID. This endpoint returns the installation's details including its provider, organization, and configuration. \ No newline at end of file diff --git a/docs/references/vcs/get-repository-contents.md b/docs/references/vcs/get-repository-contents.md new file mode 100644 index 0000000000..ab5ef7f8da --- /dev/null +++ b/docs/references/vcs/get-repository-contents.md @@ -0,0 +1 @@ +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. diff --git a/docs/references/vcs/get-repository.md b/docs/references/vcs/get-repository.md new file mode 100644 index 0000000000..ee57861114 --- /dev/null +++ b/docs/references/vcs/get-repository.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/vcs/list-installations.md b/docs/references/vcs/list-installations.md new file mode 100644 index 0000000000..e77daf7db0 --- /dev/null +++ b/docs/references/vcs/list-installations.md @@ -0,0 +1 @@ +List all VCS installations configured for the current project. This endpoint returns a list of installations including their provider, organization, and other configuration details. diff --git a/docs/references/vcs/list-repositories.md b/docs/references/vcs/list-repositories.md new file mode 100644 index 0000000000..f486e9b584 --- /dev/null +++ b/docs/references/vcs/list-repositories.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/references/vcs/list-repository-branches.md b/docs/references/vcs/list-repository-branches.md new file mode 100644 index 0000000000..eea1795a3e --- /dev/null +++ b/docs/references/vcs/list-repository-branches.md @@ -0,0 +1 @@ +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. diff --git a/docs/references/vcs/update-external-deployments.md b/docs/references/vcs/update-external-deployments.md new file mode 100644 index 0000000000..22d95da9a7 --- /dev/null +++ b/docs/references/vcs/update-external-deployments.md @@ -0,0 +1 @@ +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. \ No newline at end of file diff --git a/docs/sdks/cli/GETTING_STARTED.md b/docs/sdks/cli/GETTING_STARTED.md index 564fb4d5f9..1cadb1bbda 100644 --- a/docs/sdks/cli/GETTING_STARTED.md +++ b/docs/sdks/cli/GETTING_STARTED.md @@ -59,7 +59,7 @@ My Awesome Function You can now deploy this function using ```sh -$ appwrite deploy function +$ appwrite push function ? Which functions would you like to deploy? My Awesome Function (61d1a4c81dfcd95bc834) ℹ Info Deploying function My Awesome Function ( 61d1a4c81dfcd95bc834 ) @@ -73,7 +73,7 @@ Your function has now been deployed on your Appwrite server! As soon as the buil Similarly, you can deploy all your collections to your Appwrite server using ```sh -appwrite deploy collections +appwrite push collections ``` > ### Note @@ -98,7 +98,7 @@ $ appwrite users list To create a document you can use the following command ```sh -$ appwrite database createDocument --collectionId <ID> --documentId 'unique()' --data '{ "Name": "Iron Man" }' --permissions 'read("any")' 'read("team:abc")' +$ appwrite databases create-document --database-id <DATABASE_ID> --collection-id <COLLECTION_ID> --document-id "unique()" --data '{"name": "Walter O Brein"}' --permissions 'read("any")' 'read("team:abc")' ``` ### Some Gotchas @@ -140,4 +140,4 @@ The Appwrite CLI can also work in a CI environment. The initialisation of the CL ```sh appwrite client --endpoint http://localhost/v1 --projectId <PROJECT_ID> --key <API KEY> -``` \ No newline at end of file +``` diff --git a/docs/sdks/dart/CHANGELOG.md b/docs/sdks/dart/CHANGELOG.md index a46f1dcf0f..c41413b9ec 100644 --- a/docs/sdks/dart/CHANGELOG.md +++ b/docs/sdks/dart/CHANGELOG.md @@ -1,3 +1,15 @@ +## 14.0.0 + +* Breaking changes: + * Changed the typing of `AppwriteException`'s response parameter from a `dynamic` object to an optional string (`?String`). + +## 13.0.0 + +* Fixed realtime pong response. +* Fixed issues with `chunkedUpload` method. +* Fixed type mismatch bug where `List<dynamic>` was incorrectly causing runtime type errors. +* Updated return type of `updateMfaChallenge()` from raw data to properly typed `models.Session` object. + ## 12.0.0 * Support for Appwrite 1.6 diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index abb8967f84..110b6d08c3 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -1,3 +1,13 @@ +## 15.0.0 + +* Breaking changes: + * Changed the typing of `AppwriteException`'s response parameter from a `dynamic` object to an optional string (`?String`). + +## 14.0.0 + +* Fixed realtime pong response. +* Fixed issues with `chunkedUpload` method. + ## 13.0.0 * Fixed realtime reconnection issues diff --git a/docs/tutorials/add-oauth2-provider.md b/docs/tutorials/add-oauth2-provider.md index ab33f70cb2..da5f514919 100644 --- a/docs/tutorials/add-oauth2-provider.md +++ b/docs/tutorials/add-oauth2-provider.md @@ -175,9 +175,9 @@ Please mention in your documentation what resources or API docs you used to impl ## 3. Test your provider -After you finished adding your new provider to Appwrite, you should be able to see it in your Appwrite console. Navigate to 'Project > Users > Providers' and check your new provider's settings form. +After you finish adding your new provider to Appwrite, you should be able to see it in your Appwrite console. Navigate to 'Project > Users > Providers' and check your new provider's settings form. -> To start Appwrite console from the source code, you can simply run `docker compose up -d'. +> To start the Appwrite console from the source code, you can simply run `docker compose up -d'. Add credentials and check both a successful and a failed login (where the user denies integration on the provider page). diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000000..b18f3d6d58 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,8 @@ +parameters: + level: 8 + paths: + - src/Appwrite/Transformation + scanDirectories: + - vendor/swoole/ide-helper + excludePaths: + - tests/resources \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index 4c4e55ea4e..598b730908 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="false" + stopOnFailure="true" > <extensions> <extension class="Appwrite\Tests\TestHook" /> diff --git a/public/images/sites/templates/astro-nano-dark.png b/public/images/sites/templates/astro-nano-dark.png new file mode 100644 index 0000000000..dec79ae9b2 Binary files /dev/null and b/public/images/sites/templates/astro-nano-dark.png differ diff --git a/public/images/sites/templates/astro-nano-light.png b/public/images/sites/templates/astro-nano-light.png new file mode 100644 index 0000000000..3a846c94d9 Binary files /dev/null and b/public/images/sites/templates/astro-nano-light.png differ diff --git a/public/images/sites/templates/astro-sphere-dark.png b/public/images/sites/templates/astro-sphere-dark.png new file mode 100644 index 0000000000..ba12a3bcb7 Binary files /dev/null and b/public/images/sites/templates/astro-sphere-dark.png differ diff --git a/public/images/sites/templates/astro-sphere-light.png b/public/images/sites/templates/astro-sphere-light.png new file mode 100644 index 0000000000..0a24d533d8 Binary files /dev/null and b/public/images/sites/templates/astro-sphere-light.png differ diff --git a/public/images/sites/templates/astro-starlight-dark.png b/public/images/sites/templates/astro-starlight-dark.png new file mode 100644 index 0000000000..0c8f722e7e Binary files /dev/null and b/public/images/sites/templates/astro-starlight-dark.png differ diff --git a/public/images/sites/templates/astro-starlight-light.png b/public/images/sites/templates/astro-starlight-light.png new file mode 100644 index 0000000000..bade7a585a Binary files /dev/null and b/public/images/sites/templates/astro-starlight-light.png differ diff --git a/public/images/sites/templates/astro-starlog-dark.png b/public/images/sites/templates/astro-starlog-dark.png new file mode 100644 index 0000000000..00354471c3 Binary files /dev/null and b/public/images/sites/templates/astro-starlog-dark.png differ diff --git a/public/images/sites/templates/astro-starlog-light.png b/public/images/sites/templates/astro-starlog-light.png new file mode 100644 index 0000000000..4eb8cd7b19 Binary files /dev/null and b/public/images/sites/templates/astro-starlog-light.png differ diff --git a/public/images/sites/templates/astro-starter-dark.png b/public/images/sites/templates/astro-starter-dark.png new file mode 100644 index 0000000000..3d064c5cdd Binary files /dev/null and b/public/images/sites/templates/astro-starter-dark.png differ diff --git a/public/images/sites/templates/astro-starter-light.png b/public/images/sites/templates/astro-starter-light.png new file mode 100644 index 0000000000..3d064c5cdd Binary files /dev/null and b/public/images/sites/templates/astro-starter-light.png differ diff --git a/public/images/sites/templates/docusaurus-dark.png b/public/images/sites/templates/docusaurus-dark.png new file mode 100644 index 0000000000..916ce071ec Binary files /dev/null and b/public/images/sites/templates/docusaurus-dark.png differ diff --git a/public/images/sites/templates/docusaurus-light.png b/public/images/sites/templates/docusaurus-light.png new file mode 100644 index 0000000000..916ce071ec Binary files /dev/null and b/public/images/sites/templates/docusaurus-light.png differ diff --git a/public/images/sites/templates/littlelink-dark.png b/public/images/sites/templates/littlelink-dark.png new file mode 100644 index 0000000000..fe94d21b53 Binary files /dev/null and b/public/images/sites/templates/littlelink-dark.png differ diff --git a/public/images/sites/templates/littlelink-light.png b/public/images/sites/templates/littlelink-light.png new file mode 100644 index 0000000000..79392906c3 Binary files /dev/null and b/public/images/sites/templates/littlelink-light.png differ diff --git a/public/images/sites/templates/logspot-dark.png b/public/images/sites/templates/logspot-dark.png new file mode 100644 index 0000000000..236ca177c6 Binary files /dev/null and b/public/images/sites/templates/logspot-dark.png differ diff --git a/public/images/sites/templates/logspot-light.png b/public/images/sites/templates/logspot-light.png new file mode 100644 index 0000000000..236ca177c6 Binary files /dev/null and b/public/images/sites/templates/logspot-light.png differ diff --git a/public/images/sites/templates/lynx-starter-dark.png b/public/images/sites/templates/lynx-starter-dark.png new file mode 100644 index 0000000000..017b00907f Binary files /dev/null and b/public/images/sites/templates/lynx-starter-dark.png differ diff --git a/public/images/sites/templates/lynx-starter-light.png b/public/images/sites/templates/lynx-starter-light.png new file mode 100644 index 0000000000..0ffb0cfa43 Binary files /dev/null and b/public/images/sites/templates/lynx-starter-light.png differ diff --git a/public/images/sites/templates/magic-portfolio-dark.png b/public/images/sites/templates/magic-portfolio-dark.png new file mode 100644 index 0000000000..5fbe91977d Binary files /dev/null and b/public/images/sites/templates/magic-portfolio-dark.png differ diff --git a/public/images/sites/templates/magic-portfolio-light.png b/public/images/sites/templates/magic-portfolio-light.png new file mode 100644 index 0000000000..233c3bb046 Binary files /dev/null and b/public/images/sites/templates/magic-portfolio-light.png differ diff --git a/public/images/sites/templates/nxt-lnk-dark.png b/public/images/sites/templates/nxt-lnk-dark.png new file mode 100644 index 0000000000..004a5a487e Binary files /dev/null and b/public/images/sites/templates/nxt-lnk-dark.png differ diff --git a/public/images/sites/templates/nxt-lnk-light.png b/public/images/sites/templates/nxt-lnk-light.png new file mode 100644 index 0000000000..43a93ed3f7 Binary files /dev/null and b/public/images/sites/templates/nxt-lnk-light.png differ diff --git a/public/images/sites/templates/onelink-dark.png b/public/images/sites/templates/onelink-dark.png new file mode 100644 index 0000000000..691214e861 Binary files /dev/null and b/public/images/sites/templates/onelink-dark.png differ diff --git a/public/images/sites/templates/onelink-light.png b/public/images/sites/templates/onelink-light.png new file mode 100644 index 0000000000..63f4a506f5 Binary files /dev/null and b/public/images/sites/templates/onelink-light.png differ diff --git a/public/images/sites/templates/remix-starter-dark.png b/public/images/sites/templates/remix-starter-dark.png new file mode 100644 index 0000000000..47c0cc0394 Binary files /dev/null and b/public/images/sites/templates/remix-starter-dark.png differ diff --git a/public/images/sites/templates/remix-starter-light.png b/public/images/sites/templates/remix-starter-light.png new file mode 100644 index 0000000000..73c2d12625 Binary files /dev/null and b/public/images/sites/templates/remix-starter-light.png differ diff --git a/public/images/sites/templates/starter-for-analog-dark.png b/public/images/sites/templates/starter-for-analog-dark.png new file mode 100644 index 0000000000..7529e08dd8 Binary files /dev/null and b/public/images/sites/templates/starter-for-analog-dark.png differ diff --git a/public/images/sites/templates/starter-for-analog-light.png b/public/images/sites/templates/starter-for-analog-light.png new file mode 100644 index 0000000000..7529e08dd8 Binary files /dev/null and b/public/images/sites/templates/starter-for-analog-light.png differ diff --git a/public/images/sites/templates/starter-for-angular-dark.png b/public/images/sites/templates/starter-for-angular-dark.png new file mode 100644 index 0000000000..a7ba12ee76 Binary files /dev/null and b/public/images/sites/templates/starter-for-angular-dark.png differ diff --git a/public/images/sites/templates/starter-for-angular-light.png b/public/images/sites/templates/starter-for-angular-light.png new file mode 100644 index 0000000000..a7ba12ee76 Binary files /dev/null and b/public/images/sites/templates/starter-for-angular-light.png differ diff --git a/public/images/sites/templates/starter-for-astro-dark.png b/public/images/sites/templates/starter-for-astro-dark.png new file mode 100644 index 0000000000..5380b32b7d Binary files /dev/null and b/public/images/sites/templates/starter-for-astro-dark.png differ diff --git a/public/images/sites/templates/starter-for-astro-light.png b/public/images/sites/templates/starter-for-astro-light.png new file mode 100644 index 0000000000..5380b32b7d Binary files /dev/null and b/public/images/sites/templates/starter-for-astro-light.png differ diff --git a/public/images/sites/templates/starter-for-flutter-dark.png b/public/images/sites/templates/starter-for-flutter-dark.png new file mode 100644 index 0000000000..760cd8d341 Binary files /dev/null and b/public/images/sites/templates/starter-for-flutter-dark.png differ diff --git a/public/images/sites/templates/starter-for-flutter-light.png b/public/images/sites/templates/starter-for-flutter-light.png new file mode 100644 index 0000000000..760cd8d341 Binary files /dev/null and b/public/images/sites/templates/starter-for-flutter-light.png differ diff --git a/public/images/sites/templates/starter-for-js-dark.png b/public/images/sites/templates/starter-for-js-dark.png new file mode 100644 index 0000000000..435b619f35 Binary files /dev/null and b/public/images/sites/templates/starter-for-js-dark.png differ diff --git a/public/images/sites/templates/starter-for-js-light.png b/public/images/sites/templates/starter-for-js-light.png new file mode 100644 index 0000000000..435b619f35 Binary files /dev/null and b/public/images/sites/templates/starter-for-js-light.png differ diff --git a/public/images/sites/templates/starter-for-nextjs-dark.png b/public/images/sites/templates/starter-for-nextjs-dark.png new file mode 100644 index 0000000000..7acc80d4d4 Binary files /dev/null and b/public/images/sites/templates/starter-for-nextjs-dark.png differ diff --git a/public/images/sites/templates/starter-for-nextjs-light.png b/public/images/sites/templates/starter-for-nextjs-light.png new file mode 100644 index 0000000000..7acc80d4d4 Binary files /dev/null and b/public/images/sites/templates/starter-for-nextjs-light.png differ diff --git a/public/images/sites/templates/starter-for-nuxt-dark.png b/public/images/sites/templates/starter-for-nuxt-dark.png new file mode 100644 index 0000000000..ab8884febd Binary files /dev/null and b/public/images/sites/templates/starter-for-nuxt-dark.png differ diff --git a/public/images/sites/templates/starter-for-nuxt-light.png b/public/images/sites/templates/starter-for-nuxt-light.png new file mode 100644 index 0000000000..ab8884febd Binary files /dev/null and b/public/images/sites/templates/starter-for-nuxt-light.png differ diff --git a/public/images/sites/templates/starter-for-react-dark.png b/public/images/sites/templates/starter-for-react-dark.png new file mode 100644 index 0000000000..dcfc0a5521 Binary files /dev/null and b/public/images/sites/templates/starter-for-react-dark.png differ diff --git a/public/images/sites/templates/starter-for-react-light.png b/public/images/sites/templates/starter-for-react-light.png new file mode 100644 index 0000000000..dcfc0a5521 Binary files /dev/null and b/public/images/sites/templates/starter-for-react-light.png differ diff --git a/public/images/sites/templates/starter-for-react-native-dark.png b/public/images/sites/templates/starter-for-react-native-dark.png new file mode 100644 index 0000000000..4bb4f80c02 Binary files /dev/null and b/public/images/sites/templates/starter-for-react-native-dark.png differ diff --git a/public/images/sites/templates/starter-for-react-native-light.png b/public/images/sites/templates/starter-for-react-native-light.png new file mode 100644 index 0000000000..4bb4f80c02 Binary files /dev/null and b/public/images/sites/templates/starter-for-react-native-light.png differ diff --git a/public/images/sites/templates/starter-for-remix-dark.png b/public/images/sites/templates/starter-for-remix-dark.png new file mode 100644 index 0000000000..76e80dde71 Binary files /dev/null and b/public/images/sites/templates/starter-for-remix-dark.png differ diff --git a/public/images/sites/templates/starter-for-remix-light.png b/public/images/sites/templates/starter-for-remix-light.png new file mode 100644 index 0000000000..76e80dde71 Binary files /dev/null and b/public/images/sites/templates/starter-for-remix-light.png differ diff --git a/public/images/sites/templates/starter-for-svelte-dark.png b/public/images/sites/templates/starter-for-svelte-dark.png new file mode 100644 index 0000000000..f25943ae48 Binary files /dev/null and b/public/images/sites/templates/starter-for-svelte-dark.png differ diff --git a/public/images/sites/templates/starter-for-svelte-light.png b/public/images/sites/templates/starter-for-svelte-light.png new file mode 100644 index 0000000000..f25943ae48 Binary files /dev/null and b/public/images/sites/templates/starter-for-svelte-light.png differ diff --git a/public/images/sites/templates/starter-for-vue-dark.png b/public/images/sites/templates/starter-for-vue-dark.png new file mode 100644 index 0000000000..9d9af29f87 Binary files /dev/null and b/public/images/sites/templates/starter-for-vue-dark.png differ diff --git a/public/images/sites/templates/starter-for-vue-light.png b/public/images/sites/templates/starter-for-vue-light.png new file mode 100644 index 0000000000..9d9af29f87 Binary files /dev/null and b/public/images/sites/templates/starter-for-vue-light.png differ diff --git a/public/images/sites/templates/template-for-blog-dark.png b/public/images/sites/templates/template-for-blog-dark.png new file mode 100644 index 0000000000..b076b918a8 Binary files /dev/null and b/public/images/sites/templates/template-for-blog-dark.png differ diff --git a/public/images/sites/templates/template-for-blog-light.png b/public/images/sites/templates/template-for-blog-light.png new file mode 100644 index 0000000000..b076b918a8 Binary files /dev/null and b/public/images/sites/templates/template-for-blog-light.png differ diff --git a/public/images/sites/templates/template-for-documentation-dark.png b/public/images/sites/templates/template-for-documentation-dark.png new file mode 100644 index 0000000000..77e9aa61e4 Binary files /dev/null and b/public/images/sites/templates/template-for-documentation-dark.png differ diff --git a/public/images/sites/templates/template-for-documentation-light.png b/public/images/sites/templates/template-for-documentation-light.png new file mode 100644 index 0000000000..77e9aa61e4 Binary files /dev/null and b/public/images/sites/templates/template-for-documentation-light.png differ diff --git a/public/images/sites/templates/template-for-event-dark.png b/public/images/sites/templates/template-for-event-dark.png new file mode 100644 index 0000000000..c3376d3ff6 Binary files /dev/null and b/public/images/sites/templates/template-for-event-dark.png differ diff --git a/public/images/sites/templates/template-for-event-light.png b/public/images/sites/templates/template-for-event-light.png new file mode 100644 index 0000000000..c97901326a Binary files /dev/null and b/public/images/sites/templates/template-for-event-light.png differ diff --git a/public/images/sites/templates/template-for-portfolio-dark.png b/public/images/sites/templates/template-for-portfolio-dark.png new file mode 100644 index 0000000000..4b4382bf80 Binary files /dev/null and b/public/images/sites/templates/template-for-portfolio-dark.png differ diff --git a/public/images/sites/templates/template-for-portfolio-light.png b/public/images/sites/templates/template-for-portfolio-light.png new file mode 100644 index 0000000000..4b4382bf80 Binary files /dev/null and b/public/images/sites/templates/template-for-portfolio-light.png differ diff --git a/public/images/sites/templates/template-for-store-dark.png b/public/images/sites/templates/template-for-store-dark.png new file mode 100644 index 0000000000..645671ab55 Binary files /dev/null and b/public/images/sites/templates/template-for-store-dark.png differ diff --git a/public/images/sites/templates/template-for-store-light.png b/public/images/sites/templates/template-for-store-light.png new file mode 100644 index 0000000000..645671ab55 Binary files /dev/null and b/public/images/sites/templates/template-for-store-light.png differ diff --git a/public/images/sites/templates/vitepress-dark.png b/public/images/sites/templates/vitepress-dark.png new file mode 100644 index 0000000000..0c68d27461 Binary files /dev/null and b/public/images/sites/templates/vitepress-dark.png differ diff --git a/public/images/sites/templates/vitepress-light.png b/public/images/sites/templates/vitepress-light.png new file mode 100644 index 0000000000..0f93de1c10 Binary files /dev/null and b/public/images/sites/templates/vitepress-light.png differ diff --git a/public/images/sites/templates/vuepress-dark.png b/public/images/sites/templates/vuepress-dark.png new file mode 100644 index 0000000000..52896878be Binary files /dev/null and b/public/images/sites/templates/vuepress-dark.png differ diff --git a/public/images/sites/templates/vuepress-light.png b/public/images/sites/templates/vuepress-light.png new file mode 100644 index 0000000000..52896878be Binary files /dev/null and b/public/images/sites/templates/vuepress-light.png differ diff --git a/public/images/vcs/qr-dark.svg b/public/images/vcs/qr-dark.svg new file mode 100644 index 0000000000..bbbc681f15 --- /dev/null +++ b/public/images/vcs/qr-dark.svg @@ -0,0 +1,18 @@ +<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg"> +<mask id="path-1-outside-1_6367_338401" maskUnits="userSpaceOnUse" x="0" y="0" width="30" height="30" fill="black"> +<rect fill="white" width="30" height="30"/> +<path d="M1 10.6C1 7.23969 1 5.55953 1.65396 4.27606C2.2292 3.14708 3.14708 2.2292 4.27606 1.65396C5.55953 1 7.23969 1 10.6 1H19.4C22.7603 1 24.4405 1 25.7239 1.65396C26.8529 2.2292 27.7708 3.14708 28.346 4.27606C29 5.55953 29 7.23969 29 10.6V19.4C29 22.7603 29 24.4405 28.346 25.7239C27.7708 26.8529 26.8529 27.7708 25.7239 28.346C24.4405 29 22.7603 29 19.4 29H10.6C7.23969 29 5.55953 29 4.27606 28.346C3.14708 27.7708 2.2292 26.8529 1.65396 25.7239C1 24.4405 1 22.7603 1 19.4V10.6Z"/> +</mask> +<path d="M1 10.6C1 7.23969 1 5.55953 1.65396 4.27606C2.2292 3.14708 3.14708 2.2292 4.27606 1.65396C5.55953 1 7.23969 1 10.6 1H19.4C22.7603 1 24.4405 1 25.7239 1.65396C26.8529 2.2292 27.7708 3.14708 28.346 4.27606C29 5.55953 29 7.23969 29 10.6V19.4C29 22.7603 29 24.4405 28.346 25.7239C27.7708 26.8529 26.8529 27.7708 25.7239 28.346C24.4405 29 22.7603 29 19.4 29H10.6C7.23969 29 5.55953 29 4.27606 28.346C3.14708 27.7708 2.2292 26.8529 1.65396 25.7239C1 24.4405 1 22.7603 1 19.4V10.6Z" fill="#1D1D21"/> +<path d="M4.27606 28.346L4.73005 27.455L4.27606 28.346ZM1.65396 25.7239L0.762954 26.1779L1.65396 25.7239ZM28.346 25.7239L29.237 26.1779L28.346 25.7239ZM25.7239 28.346L26.1779 29.237L25.7239 28.346ZM28.346 4.27606L27.455 4.73005L28.346 4.27606ZM10.6 2H19.4V0H10.6V2ZM28 10.6V19.4H30V10.6H28ZM19.4 28H10.6V30H19.4V28ZM2 19.4V10.6H0V19.4H2ZM10.6 28C8.90334 28 7.69099 27.9992 6.74064 27.9216C5.80197 27.8449 5.20731 27.6982 4.73005 27.455L3.82207 29.237C4.62827 29.6478 5.51543 29.8281 6.57778 29.9149C7.62846 30.0008 8.93634 30 10.6 30V28ZM0 19.4C0 21.0637 -0.000777706 22.3715 0.0850662 23.4222C0.171864 24.4846 0.352173 25.3717 0.762954 26.1779L2.54497 25.27C2.30179 24.7927 2.15512 24.198 2.07842 23.2594C2.00078 22.309 2 21.0967 2 19.4H0ZM4.73005 27.455C3.78924 26.9757 3.02433 26.2108 2.54497 25.27L0.762954 26.1779C1.43407 27.4951 2.50493 28.5659 3.82207 29.237L4.73005 27.455ZM28 19.4C28 21.0967 27.9992 22.309 27.9216 23.2594C27.8449 24.198 27.6982 24.7927 27.455 25.27L29.237 26.1779C29.6478 25.3717 29.8281 24.4846 29.9149 23.4222C30.0008 22.3715 30 21.0637 30 19.4H28ZM19.4 30C21.0637 30 22.3715 30.0008 23.4222 29.9149C24.4846 29.8281 25.3717 29.6478 26.1779 29.237L25.27 27.455C24.7927 27.6982 24.198 27.8449 23.2594 27.9216C22.309 27.9992 21.0967 28 19.4 28V30ZM27.455 25.27C26.9757 26.2108 26.2108 26.9757 25.27 27.455L26.1779 29.237C27.4951 28.5659 28.5659 27.4951 29.237 26.1779L27.455 25.27ZM19.4 2C21.0967 2 22.309 2.00078 23.2594 2.07842C24.198 2.15512 24.7927 2.30179 25.27 2.54497L26.1779 0.762954C25.3717 0.352173 24.4846 0.171864 23.4222 0.0850662C22.3715 -0.000777706 21.0637 0 19.4 0V2ZM30 10.6C30 8.93634 30.0008 7.62846 29.9149 6.57778C29.8281 5.51543 29.6478 4.62827 29.237 3.82207L27.455 4.73005C27.6982 5.20731 27.8449 5.80197 27.9216 6.74064C27.9992 7.69099 28 8.90334 28 10.6H30ZM25.27 2.54497C26.2108 3.02433 26.9757 3.78924 27.455 4.73005L29.237 3.82207C28.5659 2.50493 27.4951 1.43407 26.1779 0.762954L25.27 2.54497ZM10.6 0C8.93634 0 7.62846 -0.000777706 6.57778 0.0850662C5.51543 0.171864 4.62827 0.352173 3.82207 0.762954L4.73005 2.54497C5.20731 2.30179 5.80197 2.15512 6.74064 2.07842C7.69099 2.00078 8.90334 2 10.6 2V0ZM2 10.6C2 8.90334 2.00078 7.69099 2.07842 6.74064C2.15512 5.80197 2.30179 5.20731 2.54497 4.73005L0.762954 3.82207C0.352173 4.62827 0.171864 5.51543 0.0850662 6.57778C-0.000777706 7.62846 0 8.93634 0 10.6H2ZM3.82207 0.762954C2.50493 1.43407 1.43407 2.50493 0.762954 3.82207L2.54497 4.73005C3.02433 3.78924 3.78924 3.02433 4.73005 2.54497L3.82207 0.762954Z" fill="#414146" mask="url(#path-1-outside-1_6367_338401)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M8 9C8 8.44772 8.44772 8 9 8H12C12.5523 8 13 8.44772 13 9V12C13 12.5523 12.5523 13 12 13H9C8.44772 13 8 12.5523 8 12V9ZM10 11V10H11V11H10Z" fill="#818186"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M8 18C8 17.4477 8.44772 17 9 17H12C12.5523 17 13 17.4477 13 18V21C13 21.5523 12.5523 22 12 22H9C8.44772 22 8 21.5523 8 21V18ZM10 20V19H11V20H10Z" fill="#818186"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M18 8C17.4477 8 17 8.44772 17 9V12C17 12.5523 17.4477 13 18 13H21C21.5523 13 22 12.5523 22 12V9C22 8.44772 21.5523 8 21 8H18ZM19 10V11H20V10H19Z" fill="#818186"/> +<path d="M16 9C16 8.44772 15.5523 8 15 8C14.4477 8 14 8.44772 14 9V10C14 10.5523 14.4477 11 15 11C15.5523 11 16 10.5523 16 10V9Z" fill="#818186"/> +<path d="M15 12C15.5523 12 16 12.4477 16 13V14H18C18.5523 14 19 14.4477 19 15C19 15.5523 18.5523 16 18 16H15C14.4477 16 14 15.5523 14 15V13C14 12.4477 14.4477 12 15 12Z" fill="#818186"/> +<path d="M21 14C20.4477 14 20 14.4477 20 15C20 15.5523 20.4477 16 21 16C21.5523 16 22 15.5523 22 15C22 14.4477 21.5523 14 21 14Z" fill="#818186"/> +<path d="M14 18C14 17.4477 14.4477 17 15 17H16C16.5523 17 17 17.4477 17 18C17 18.5523 16.5523 19 16 19V21C16 21.5523 15.5523 22 15 22C14.4477 22 14 21.5523 14 21V18Z" fill="#818186"/> +<path d="M12 16C12.5523 16 13 15.5523 13 15C13 14.4477 12.5523 14 12 14H9C8.44772 14 8 14.4477 8 15C8 15.5523 8.44772 16 9 16H12Z" fill="#818186"/> +<path d="M22 18C22 18.5523 21.5523 19 21 19H19C18.4477 19 18 18.5523 18 18C18 17.4477 18.4477 17 19 17H21C21.5523 17 22 17.4477 22 18Z" fill="#818186"/> +<path d="M21 22C21.5523 22 22 21.5523 22 21C22 20.4477 21.5523 20 21 20H18C17.4477 20 17 20.4477 17 21C17 21.5523 17.4477 22 18 22H21Z" fill="#818186"/> +</svg> diff --git a/public/images/vcs/qr-light.svg b/public/images/vcs/qr-light.svg new file mode 100644 index 0000000000..5026db975d --- /dev/null +++ b/public/images/vcs/qr-light.svg @@ -0,0 +1,18 @@ +<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg"> +<mask id="path-1-outside-1_6367_338394" maskUnits="userSpaceOnUse" x="0" y="0" width="30" height="30" fill="black"> +<rect fill="white" width="30" height="30"/> +<path d="M1 10.6C1 7.23969 1 5.55953 1.65396 4.27606C2.2292 3.14708 3.14708 2.2292 4.27606 1.65396C5.55953 1 7.23969 1 10.6 1H19.4C22.7603 1 24.4405 1 25.7239 1.65396C26.8529 2.2292 27.7708 3.14708 28.346 4.27606C29 5.55953 29 7.23969 29 10.6V19.4C29 22.7603 29 24.4405 28.346 25.7239C27.7708 26.8529 26.8529 27.7708 25.7239 28.346C24.4405 29 22.7603 29 19.4 29H10.6C7.23969 29 5.55953 29 4.27606 28.346C3.14708 27.7708 2.2292 26.8529 1.65396 25.7239C1 24.4405 1 22.7603 1 19.4V10.6Z"/> +</mask> +<path d="M1 10.6C1 7.23969 1 5.55953 1.65396 4.27606C2.2292 3.14708 3.14708 2.2292 4.27606 1.65396C5.55953 1 7.23969 1 10.6 1H19.4C22.7603 1 24.4405 1 25.7239 1.65396C26.8529 2.2292 27.7708 3.14708 28.346 4.27606C29 5.55953 29 7.23969 29 10.6V19.4C29 22.7603 29 24.4405 28.346 25.7239C27.7708 26.8529 26.8529 27.7708 25.7239 28.346C24.4405 29 22.7603 29 19.4 29H10.6C7.23969 29 5.55953 29 4.27606 28.346C3.14708 27.7708 2.2292 26.8529 1.65396 25.7239C1 24.4405 1 22.7603 1 19.4V10.6Z" fill="white"/> +<path d="M4.27606 28.346L4.73005 27.455L4.27606 28.346ZM1.65396 25.7239L0.762954 26.1779L1.65396 25.7239ZM28.346 25.7239L29.237 26.1779L28.346 25.7239ZM25.7239 28.346L26.1779 29.237L25.7239 28.346ZM28.346 4.27606L27.455 4.73005L28.346 4.27606ZM10.6 2H19.4V0H10.6V2ZM28 10.6V19.4H30V10.6H28ZM19.4 28H10.6V30H19.4V28ZM2 19.4V10.6H0V19.4H2ZM10.6 28C8.90334 28 7.69099 27.9992 6.74064 27.9216C5.80197 27.8449 5.20731 27.6982 4.73005 27.455L3.82207 29.237C4.62827 29.6478 5.51543 29.8281 6.57778 29.9149C7.62846 30.0008 8.93634 30 10.6 30V28ZM0 19.4C0 21.0637 -0.000777706 22.3715 0.0850662 23.4222C0.171864 24.4846 0.352173 25.3717 0.762954 26.1779L2.54497 25.27C2.30179 24.7927 2.15512 24.198 2.07842 23.2594C2.00078 22.309 2 21.0967 2 19.4H0ZM4.73005 27.455C3.78924 26.9757 3.02433 26.2108 2.54497 25.27L0.762954 26.1779C1.43407 27.4951 2.50493 28.5659 3.82207 29.237L4.73005 27.455ZM28 19.4C28 21.0967 27.9992 22.309 27.9216 23.2594C27.8449 24.198 27.6982 24.7927 27.455 25.27L29.237 26.1779C29.6478 25.3717 29.8281 24.4846 29.9149 23.4222C30.0008 22.3715 30 21.0637 30 19.4H28ZM19.4 30C21.0637 30 22.3715 30.0008 23.4222 29.9149C24.4846 29.8281 25.3717 29.6478 26.1779 29.237L25.27 27.455C24.7927 27.6982 24.198 27.8449 23.2594 27.9216C22.309 27.9992 21.0967 28 19.4 28V30ZM27.455 25.27C26.9757 26.2108 26.2108 26.9757 25.27 27.455L26.1779 29.237C27.4951 28.5659 28.5659 27.4951 29.237 26.1779L27.455 25.27ZM19.4 2C21.0967 2 22.309 2.00078 23.2594 2.07842C24.198 2.15512 24.7927 2.30179 25.27 2.54497L26.1779 0.762954C25.3717 0.352173 24.4846 0.171864 23.4222 0.0850662C22.3715 -0.000777706 21.0637 0 19.4 0V2ZM30 10.6C30 8.93634 30.0008 7.62846 29.9149 6.57778C29.8281 5.51543 29.6478 4.62827 29.237 3.82207L27.455 4.73005C27.6982 5.20731 27.8449 5.80197 27.9216 6.74064C27.9992 7.69099 28 8.90334 28 10.6H30ZM25.27 2.54497C26.2108 3.02433 26.9757 3.78924 27.455 4.73005L29.237 3.82207C28.5659 2.50493 27.4951 1.43407 26.1779 0.762954L25.27 2.54497ZM10.6 0C8.93634 0 7.62846 -0.000777706 6.57778 0.0850662C5.51543 0.171864 4.62827 0.352173 3.82207 0.762954L4.73005 2.54497C5.20731 2.30179 5.80197 2.15512 6.74064 2.07842C7.69099 2.00078 8.90334 2 10.6 2V0ZM2 10.6C2 8.90334 2.00078 7.69099 2.07842 6.74064C2.15512 5.80197 2.30179 5.20731 2.54497 4.73005L0.762954 3.82207C0.352173 4.62827 0.171864 5.51543 0.0850662 6.57778C-0.000777706 7.62846 0 8.93634 0 10.6H2ZM3.82207 0.762954C2.50493 1.43407 1.43407 2.50493 0.762954 3.82207L2.54497 4.73005C3.02433 3.78924 3.78924 3.02433 4.73005 2.54497L3.82207 0.762954Z" fill="#D8D8DB" mask="url(#path-1-outside-1_6367_338394)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M8 9C8 8.44772 8.44772 8 9 8H12C12.5523 8 13 8.44772 13 9V12C13 12.5523 12.5523 13 12 13H9C8.44772 13 8 12.5523 8 12V9ZM10 11V10H11V11H10Z" fill="#97979B"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M8 18C8 17.4477 8.44772 17 9 17H12C12.5523 17 13 17.4477 13 18V21C13 21.5523 12.5523 22 12 22H9C8.44772 22 8 21.5523 8 21V18ZM10 20V19H11V20H10Z" fill="#97979B"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M18 8C17.4477 8 17 8.44772 17 9V12C17 12.5523 17.4477 13 18 13H21C21.5523 13 22 12.5523 22 12V9C22 8.44772 21.5523 8 21 8H18ZM19 10V11H20V10H19Z" fill="#97979B"/> +<path d="M16 9C16 8.44772 15.5523 8 15 8C14.4477 8 14 8.44772 14 9V10C14 10.5523 14.4477 11 15 11C15.5523 11 16 10.5523 16 10V9Z" fill="#97979B"/> +<path d="M15 12C15.5523 12 16 12.4477 16 13V14H18C18.5523 14 19 14.4477 19 15C19 15.5523 18.5523 16 18 16H15C14.4477 16 14 15.5523 14 15V13C14 12.4477 14.4477 12 15 12Z" fill="#97979B"/> +<path d="M21 14C20.4477 14 20 14.4477 20 15C20 15.5523 20.4477 16 21 16C21.5523 16 22 15.5523 22 15C22 14.4477 21.5523 14 21 14Z" fill="#97979B"/> +<path d="M14 18C14 17.4477 14.4477 17 15 17H16C16.5523 17 17 17.4477 17 18C17 18.5523 16.5523 19 16 19V21C16 21.5523 15.5523 22 15 22C14.4477 22 14 21.5523 14 21V18Z" fill="#97979B"/> +<path d="M12 16C12.5523 16 13 15.5523 13 15C13 14.4477 12.5523 14 12 14H9C8.44772 14 8 14.4477 8 15C8 15.5523 8.44772 16 9 16H12Z" fill="#97979B"/> +<path d="M22 18C22 18.5523 21.5523 19 21 19H19C18.4477 19 18 18.5523 18 18C18 17.4477 18.4477 17 19 17H21C21.5523 17 22 17.4477 22 18Z" fill="#97979B"/> +<path d="M21 22C21.5523 22 22 21.5523 22 21C22 20.4477 21.5523 20 21 20H18C17.4477 20 17 20.4477 17 21C17 21.5523 17.4477 22 18 22H21Z" fill="#97979B"/> +</svg> diff --git a/public/images/vcs/status-building-dark.gif b/public/images/vcs/status-building-dark.gif new file mode 100644 index 0000000000..6d4afe72a1 Binary files /dev/null and b/public/images/vcs/status-building-dark.gif differ diff --git a/public/images/vcs/status-building-light.gif b/public/images/vcs/status-building-light.gif new file mode 100644 index 0000000000..c64a7643c1 Binary files /dev/null and b/public/images/vcs/status-building-light.gif differ diff --git a/public/images/vcs/status-failed-dark.png b/public/images/vcs/status-failed-dark.png new file mode 100644 index 0000000000..c6508e93bc Binary files /dev/null and b/public/images/vcs/status-failed-dark.png differ diff --git a/public/images/vcs/status-failed-light.png b/public/images/vcs/status-failed-light.png new file mode 100644 index 0000000000..0e4d4533d0 Binary files /dev/null and b/public/images/vcs/status-failed-light.png differ diff --git a/public/images/vcs/status-ready-dark.png b/public/images/vcs/status-ready-dark.png new file mode 100644 index 0000000000..7408fb0cba Binary files /dev/null and b/public/images/vcs/status-ready-dark.png differ diff --git a/public/images/vcs/status-ready-light.png b/public/images/vcs/status-ready-light.png new file mode 100644 index 0000000000..87e141fcfe Binary files /dev/null and b/public/images/vcs/status-ready-light.png differ diff --git a/public/images/vcs/status-waiting-dark.png b/public/images/vcs/status-waiting-dark.png new file mode 100644 index 0000000000..29a4ee540c Binary files /dev/null and b/public/images/vcs/status-waiting-dark.png differ diff --git a/public/images/vcs/status-waiting-light.png b/public/images/vcs/status-waiting-light.png new file mode 100644 index 0000000000..676d530cf4 Binary files /dev/null and b/public/images/vcs/status-waiting-light.png differ diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index 1e8109622e..9af5045fa4 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -43,6 +43,13 @@ class Auth public const USER_ROLE_APPS = 'apps'; public const USER_ROLE_SYSTEM = 'system'; + /** + * Activity associated with user or the app. + */ + public const ACTIVITY_TYPE_APP = 'app'; + public const ACTIVITY_TYPE_USER = 'user'; + public const ACTIVITY_TYPE_GUEST = 'guest'; + /** * Token Types. */ @@ -96,6 +103,11 @@ class Auth */ public static $cookieName = 'a_session'; + /** + * @var string + */ + public static $cookieNamePreview = 'a_jwt_console'; + /** * User Unique ID. * diff --git a/src/Appwrite/Auth/Key.php b/src/Appwrite/Auth/Key.php new file mode 100644 index 0000000000..44a75a6ee3 --- /dev/null +++ b/src/Appwrite/Auth/Key.php @@ -0,0 +1,200 @@ +<?php + +namespace Appwrite\Auth; + +use Ahc\Jwt\JWT; +use Ahc\Jwt\JWTException; +use Appwrite\Extend\Exception; +use Utopia\Config\Config; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\System\System; + +class Key +{ + public function __construct( + protected string $projectId, + protected string $type, + protected string $role, + protected array $scopes, + protected string $name, + protected bool $expired = false, + protected array $disabledMetrics = [], + protected bool $hostnameOverride = false, + protected bool $bannerDisabled = false, + protected bool $projectCheckDisabled = false, + protected bool $previewAuthDisabled = false, + protected bool $deploymentStatusIgnored = false, + ) { + } + + public function getProjectId(): string + { + return $this->projectId; + } + + public function getType(): string + { + return $this->type; + } + + public function getRole(): string + { + return $this->role; + } + + public function getScopes(): array + { + return $this->scopes; + } + + public function getName(): string + { + return $this->name; + } + + public function isExpired(): bool + { + return $this->expired; + } + + public function getDisabledMetrics(): array + { + return $this->disabledMetrics; + } + + + public function getHostnameOverride(): bool + { + return $this->hostnameOverride; + } + + + public function isBannerDisabled(): bool + { + return $this->bannerDisabled; + } + + public function isPreviewAuthDisabled(): bool + { + return $this->previewAuthDisabled; + } + + public function isDeploymentStatusIgnored(): bool + { + return $this->deploymentStatusIgnored; + } + + public function isProjectCheckDisabled(): bool + { + return $this->projectCheckDisabled; + } + + /** + * Decode the given secret key into a Key object, containing the project ID, type, role, scopes, and name. + * Can be a stored API key or a dynamic key (JWT). + * + * @param Document $project + * @param string $key + * @return Key + * @throws Exception + */ + public static function decode( + Document $project, + string $key + ): Key { + if (\str_contains($key, '_')) { + [$type, $secret] = \explode('_', $key, 2); + } else { + $type = API_KEY_STANDARD; + $secret = $key; + } + + $role = Auth::USER_ROLE_APPS; + $roles = Config::getParam('roles', []); + $scopes = $roles[Auth::USER_ROLE_APPS]['scopes'] ?? []; + $expired = false; + + $guestKey = new Key( + $project->getId(), + $type, + Auth::USER_ROLE_GUESTS, + $roles[Auth::USER_ROLE_GUESTS]['scopes'] ?? [], + 'UNKNOWN' + ); + + switch ($type) { + case API_KEY_DYNAMIC: + $jwtObj = new JWT( + key: System::getEnv('_APP_OPENSSL_KEY_V1'), + algo: 'HS256', + maxAge: 86400, + leeway: 0 + ); + + try { + $payload = $jwtObj->decode($secret); + } catch (JWTException) { + $expired = true; + } + + $name = $payload['name'] ?? 'Dynamic Key'; + $projectId = $payload['projectId'] ?? ''; + $disabledMetrics = $payload['disabledMetrics'] ?? []; + $hostnameOverride = $payload['hostnameOverride'] ?? false; + $bannerDisabled = $payload['bannerDisabled'] ?? false; + $projectCheckDisabled = $payload['projectCheckDisabled'] ?? false; + $previewAuthDisabled = $payload['previewAuthDisabled'] ?? false; + $deploymentStatusIgnored = $payload['deploymentStatusIgnored'] ?? false; + $scopes = \array_merge($payload['scopes'] ?? [], $scopes); + + if (!$projectCheckDisabled && $projectId !== $project->getId()) { + return $guestKey; + } + + return new Key( + $projectId, + $type, + $role, + $scopes, + $name, + $expired, + $disabledMetrics, + $hostnameOverride, + $bannerDisabled, + $projectCheckDisabled, + $previewAuthDisabled, + $deploymentStatusIgnored + ); + case API_KEY_STANDARD: + $key = $project->find( + key: 'secret', + find: $key, + subject: 'keys' + ); + + if (!$key) { + return $guestKey; + } + + $expire = $key->getAttribute('expire'); + if (!empty($expire) && $expire < DateTime::formatTz(DateTime::now())) { + $expired = true; + } + + $name = $key->getAttribute('name', 'UNKNOWN'); + $scopes = \array_merge($key->getAttribute('scopes', []), $scopes); + + return new Key( + $project->getId(), + $type, + $role, + $scopes, + $name, + $expired + ); + default: + return $guestKey; + } + } +} diff --git a/src/Appwrite/Auth/OAuth2/Amazon.php b/src/Appwrite/Auth/OAuth2/Amazon.php index d1d2cb5a38..2fa3f4cfe9 100644 --- a/src/Appwrite/Auth/OAuth2/Amazon.php +++ b/src/Appwrite/Auth/OAuth2/Amazon.php @@ -43,7 +43,7 @@ class Amazon extends OAuth2 */ public function parseState(string $state) { - return \json_decode(\html_entity_decode($state), true); + return \json_decode(\urldecode(\html_entity_decode($state)), true); } @@ -56,7 +56,7 @@ class Amazon extends OAuth2 'response_type' => 'code', 'client_id' => $this->appID, 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state), + 'state' => \urlencode(\json_encode($this->state)), 'redirect_uri' => $this->callback ]); } diff --git a/src/Appwrite/Auth/OAuth2/Firebase.php b/src/Appwrite/Auth/OAuth2/Firebase.php deleted file mode 100644 index 0e2859e32c..0000000000 --- a/src/Appwrite/Auth/OAuth2/Firebase.php +++ /dev/null @@ -1,389 +0,0 @@ -<?php - -namespace Appwrite\Auth\OAuth2; - -use Appwrite\Auth\OAuth2; - -class Firebase extends OAuth2 -{ - /** - * @var array - */ - protected array $user = []; - - /** - * @var array - */ - protected array $tokens = []; - - /** - * @var array - */ - protected array $scopes = [ - 'https://www.googleapis.com/auth/firebase', - 'https://www.googleapis.com/auth/datastore', - 'https://www.googleapis.com/auth/cloud-platform', - 'https://www.googleapis.com/auth/identitytoolkit', - 'https://www.googleapis.com/auth/userinfo.profile' - ]; - - /** - * @var array - */ - protected array $iamPermissions = [ - // Database - 'datastore.databases.get', - 'datastore.databases.list', - 'datastore.entities.get', - 'datastore.entities.list', - 'datastore.indexes.get', - 'datastore.indexes.list', - // Generic Firebase permissions - 'firebase.projects.get', - - // Auth - 'firebaseauth.configs.get', - 'firebaseauth.configs.getHashConfig', - 'firebaseauth.configs.getSecret', - 'firebaseauth.users.get', - 'identitytoolkit.tenants.get', - 'identitytoolkit.tenants.list', - - // IAM Assignment - 'iam.serviceAccounts.list', - - // Storage - 'storage.buckets.get', - 'storage.buckets.list', - 'storage.objects.get', - 'storage.objects.list' - ]; - - /** - * @return string - */ - public function getName(): string - { - return 'firebase'; - } - - /** - * @return string - */ - public function getLoginURL(): string - { - return 'https://accounts.google.com/o/oauth2/v2/auth?' . \http_build_query([ - 'access_type' => 'offline', - 'client_id' => $this->appID, - 'redirect_uri' => $this->callback, - 'scope' => \implode(' ', $this->getScopes()), - 'state' => \json_encode($this->state), - 'response_type' => 'code', - 'prompt' => 'consent', - ]); - } - - /** - * @param string $code - * - * @return array - */ - protected function getTokens(string $code): array - { - if (empty($this->tokens)) { - $response = $this->request( - 'POST', - 'https://oauth2.googleapis.com/token', - [], - \http_build_query([ - 'client_id' => $this->appID, - 'redirect_uri' => $this->callback, - 'client_secret' => $this->appSecret, - 'code' => $code, - 'grant_type' => 'authorization_code' - ]) - ); - - $this->tokens = \json_decode($response, true); - } - - return $this->tokens; - } - - /** - * @param string $refreshToken - * - * @return array - */ - public function refreshTokens(string $refreshToken): array - { - $response = $this->request( - 'POST', - 'https://oauth2.googleapis.com/token', - [], - \http_build_query([ - 'client_id' => $this->appID, - 'client_secret' => $this->appSecret, - 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken - ]) - ); - - $output = []; - \parse_str($response, $output); - $this->tokens = $output; - - if (empty($this->tokens['refresh_token'])) { - $this->tokens['refresh_token'] = $refreshToken; - } - - return $this->tokens; - } - - - /** - * @param string $accessToken - * - * @return string - */ - public function getUserID(string $accessToken): string - { - $user = $this->getUser($accessToken); - - return $user['id'] ?? ''; - } - - /** - * @param string $accessToken - * - * @return string - */ - public function getUserEmail(string $accessToken): string - { - $user = $this->getUser($accessToken); - - return $user['email'] ?? ''; - } - - - /** - * Check if the OAuth email is verified - * - * @link https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user - * - * @param string $accessToken - * - * @return bool - */ - public function isEmailVerified(string $accessToken): bool - { - $user = $this->getUser($accessToken); - - if ($user['verified'] ?? false) { - return true; - } - - return false; - } - - /** - * @param string $accessToken - * - * @return string - */ - public function getUserName(string $accessToken): string - { - $user = $this->getUser($accessToken); - - return $user['name'] ?? ''; - } - - /** - * @param string $accessToken - * - * @return array - */ - protected function getUser(string $accessToken) - { - if (empty($this->user)) { - $response = $this->request( - 'GET', - 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' . \urlencode($accessToken), - [], - ); - - $this->user = \json_decode($response, true); - } - - return $this->user; - } - - public function getProjects(string $accessToken): array - { - $projects = $this->request('GET', 'https://firebase.googleapis.com/v1beta1/projects', ['Authorization: Bearer ' . \urlencode($accessToken)]); - - $projects = \json_decode($projects, true); - - return $projects['results']; - } - - /* - Be careful with the setIAMPolicy method, it will overwrite all existing policies - **/ - public function assignIAMRole(string $accessToken, string $email, string $projectId, array $role) - { - // Get IAM Roles - $iamRoles = $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/' . $projectId . ':getIamPolicy', [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ]); - - $iamRoles = \json_decode($iamRoles, true); - - $iamRoles['bindings'][] = [ - 'role' => $role['name'], - 'members' => [ - 'serviceAccount:' . $email - ] - ]; - - // Set IAM Roles - $this->request('POST', 'https://cloudresourcemanager.googleapis.com/v1/projects/' . $projectId . ':setIamPolicy', [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ], \json_encode([ - 'policy' => $iamRoles - ])); - } - - private function generateRandomString($length = 10): string - { - $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $charactersLength = strlen($characters); - $randomString = ''; - for ($i = 0; $i < $length; $i++) { - $randomString .= $characters[random_int(0, $charactersLength - 1)]; - } - return $randomString; - } - - private function createCustomRole(string $accessToken, string $projectId): array - { - // Check if role already exists - try { - $role = $this->request('GET', 'https://iam.googleapis.com/v1/projects/' . $projectId . '/roles/appwriteMigrations', [ - 'Content-Type: application/json', - 'Authorization: Bearer ' . \urlencode($accessToken), - ]); - - $role = \json_decode($role, true); - - return $role; - } catch (\Throwable $e) { - if ($e->getCode() !== 404) { - throw $e; - } - } - - // Create role if doesn't exist or isn't correct - $role = $this->request( - 'POST', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/roles/', - [ - 'Content-Type: application/json', - 'Authorization: Bearer ' . \urlencode($accessToken), - ], - \json_encode( - [ - 'roleId' => 'appwriteMigrations', - 'role' => [ - 'title' => 'Appwrite Migrations', - 'description' => 'A helper role for Appwrite Migrations', - 'includedPermissions' => $this->iamPermissions, - 'stage' => 'GA' - ] - ] - ) - ); - - return json_decode($role, true); - } - - public function createServiceAccount(string $accessToken, string $projectId): array - { - // Create Service Account - $uid = $this->generateRandomString(); - - $response = $this->request( - 'POST', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts', - [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ], - \json_encode([ - 'accountId' => 'appwrite-' . $uid, - 'serviceAccount' => [ - 'displayName' => 'Appwrite Migrations ' . $uid - ] - ]) - ); - - $response = json_decode($response, true); - - // Create and assign IAM Roles - $role = $this->createCustomRole($accessToken, $projectId); - - \sleep(1); // Wait for IAM to propagate changes. - - $this->assignIAMRole($accessToken, $response['email'], $projectId, $role); - - // Create Service Account Key - $responseKey = $this->request( - 'POST', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts/' . $response['email'] . '/keys', - [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ] - ); - - $responseKey = json_decode($responseKey, true); - - return json_decode(base64_decode($responseKey['privateKeyData']), true); - } - - public function cleanupServiceAccounts(string $accessToken, string $projectId) - { - // List Service Accounts - $response = $this->request( - 'GET', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts', - [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ] - ); - - $response = json_decode($response, true); - - if (empty($response['accounts'])) { - return false; - } - - foreach ($response['accounts'] as $account) { - if (strpos($account['email'], 'appwrite-') !== false) { - $this->request( - 'DELETE', - 'https://iam.googleapis.com/v1/projects/' . $projectId . '/serviceAccounts/' . $account['email'], - [ - 'Authorization: Bearer ' . \urlencode($accessToken), - 'Content-Type: application/json' - ] - ); - } - } - - return true; - } -} diff --git a/src/Appwrite/Auth/OAuth2/Slack.php b/src/Appwrite/Auth/OAuth2/Slack.php index 8898f4d1f7..9c87e45ed6 100644 --- a/src/Appwrite/Auth/OAuth2/Slack.php +++ b/src/Appwrite/Auth/OAuth2/Slack.php @@ -20,10 +20,9 @@ class Slack extends OAuth2 * @var array */ protected array $scopes = [ - 'identity.avatar', - 'identity.basic', - 'identity.email', - 'identity.team' + 'openid', + 'email', + 'profile' ]; /** @@ -35,14 +34,15 @@ class Slack extends OAuth2 } /** + * @link https://api.slack.com/authentication/oauth-v2 + * * @return string */ public function getLoginURL(): string { - // https://api.slack.com/docs/oauth#step_1_-_sending_users_to_authorize_and_or_install - return 'https://slack.com/oauth/authorize?' . \http_build_query([ + return 'https://slack.com/oauth/v2/authorize?' . \http_build_query([ 'client_id' => $this->appID, - 'scope' => \implode(' ', $this->getScopes()), + 'user_scope' => \implode(' ', $this->getScopes()), 'redirect_uri' => $this->callback, 'state' => \json_encode($this->state) ]); @@ -56,16 +56,15 @@ class Slack extends OAuth2 protected function getTokens(string $code): array { if (empty($this->tokens)) { - // https://api.slack.com/docs/oauth#step_3_-_exchanging_a_verification_code_for_an_access_token $this->tokens = \json_decode($this->request( 'GET', - 'https://slack.com/api/oauth.access?' . \http_build_query([ + 'https://slack.com/api/oauth.v2.access?' . \http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'code' => $code, 'redirect_uri' => $this->callback ]) - ), true); + ), true)['authed_user'] ?? []; } return $this->tokens; @@ -80,13 +79,13 @@ class Slack extends OAuth2 { $this->tokens = \json_decode($this->request( 'GET', - 'https://slack.com/api/oauth.access?' . \http_build_query([ + 'https://slack.com/api/oauth.v2.access?' . \http_build_query([ 'client_id' => $this->appID, 'client_secret' => $this->appSecret, 'refresh_token' => $refreshToken, 'grant_type' => 'refresh_token' ]) - ), true); + ), true)['authed_user'] ?? []; if (empty($this->tokens['refresh_token'])) { $this->tokens['refresh_token'] = $refreshToken; @@ -161,9 +160,9 @@ class Slack extends OAuth2 if (empty($this->user)) { $user = $this->request( 'GET', - 'https://slack.com/api/users.identity?token=' . \urlencode($accessToken) + 'https://slack.com/api/users.identity', + ['Authorization: Bearer ' . \urlencode($accessToken)] ); - $this->user = \json_decode($user, true); } diff --git a/src/Appwrite/Auth/Validator/Phone.php b/src/Appwrite/Auth/Validator/Phone.php index 26aa687278..e74a78d265 100644 --- a/src/Appwrite/Auth/Validator/Phone.php +++ b/src/Appwrite/Auth/Validator/Phone.php @@ -2,6 +2,8 @@ namespace Appwrite\Auth\Validator; +use libphonenumber\NumberParseException; +use libphonenumber\PhoneNumberUtil; use Utopia\Validator; /** @@ -12,10 +14,12 @@ use Utopia\Validator; class Phone extends Validator { protected bool $allowEmpty; + protected PhoneNumberUtil $helper; public function __construct(bool $allowEmpty = false) { $this->allowEmpty = $allowEmpty; + $this->helper = PhoneNumberUtil::getInstance(); } /** @@ -47,6 +51,12 @@ class Phone extends Validator return true; } + try { + $this->helper->parse($value); + } catch (NumberParseException $e) { + return false; + } + return !!\preg_match('/^\+[1-9]\d{6,14}$/', $value); } diff --git a/src/Appwrite/Certificates/Adapter.php b/src/Appwrite/Certificates/Adapter.php new file mode 100644 index 0000000000..711e4c09b9 --- /dev/null +++ b/src/Appwrite/Certificates/Adapter.php @@ -0,0 +1,14 @@ +<?php + +namespace Appwrite\Certificates; + +use Utopia\Logger\Log; + +interface Adapter +{ + public function issueCertificate(string $certName, string $domain): ?string; + + public function isRenewRequired(string $domain, Log $log): bool; + + public function deleteCertificate(string $domain): void; +} diff --git a/src/Appwrite/Certificates/LetsEncrypt.php b/src/Appwrite/Certificates/LetsEncrypt.php new file mode 100644 index 0000000000..3896eab022 --- /dev/null +++ b/src/Appwrite/Certificates/LetsEncrypt.php @@ -0,0 +1,125 @@ +<?php + +namespace Appwrite\Certificates; + +use Exception; +use Utopia\App; +use Utopia\CLI\Console; +use Utopia\Database\DateTime; +use Utopia\Logger\Log; + +class LetsEncrypt implements Adapter +{ + private string $email; + + public function __construct(string $email) + { + $this->email = $email; + } + + + public function issueCertificate(string $certName, string $domain): ?string + { + $stdout = ''; + $stderr = ''; + + $staging = (App::isProduction()) ? '' : ' --dry-run'; + $exit = Console::execute( + "certbot certonly -v --webroot --noninteractive --agree-tos{$staging}" + . " --email " . $this->email + . " --cert-name " . $certName + . " -w " . APP_STORAGE_CERTIFICATES + . " -d {$domain}", + '', + $stdout, + $stderr + ); + + // Unexpected error, usually 5XX, API limits, ... + if ($exit !== 0) { + throw new Exception('Failed to issue a certificate with message: ' . $stderr); + } + + // Prepare folder in storage for domain + $path = APP_STORAGE_CERTIFICATES . '/' . $domain; + if (!\is_readable($path)) { + if (!\mkdir($path, 0755, true)) { + throw new Exception('Failed to create path for certificate.'); + } + } + + // Move generated files + if (!@\rename('/etc/letsencrypt/live/' . $certName . '/cert.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem')) { + throw new Exception('Failed to rename certificate cert.pem. Let\'s Encrypt log: ' . $stderr . ' ; ' . $stdout); + } + + if (!@\rename('/etc/letsencrypt/live/' . $certName . '/chain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/chain.pem')) { + throw new Exception('Failed to rename certificate chain.pem. Let\'s Encrypt log: ' . $stderr . ' ; ' . $stdout); + } + + if (!@\rename('/etc/letsencrypt/live/' . $certName . '/fullchain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/fullchain.pem')) { + throw new Exception('Failed to rename certificate fullchain.pem. Let\'s Encrypt log: ' . $stderr . ' ; ' . $stdout); + } + + if (!@\rename('/etc/letsencrypt/live/' . $certName . '/privkey.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/privkey.pem')) { + throw new Exception('Failed to rename certificate privkey.pem. Let\'s Encrypt log: ' . $stderr . ' ; ' . $stdout); + } + + $config = \implode(PHP_EOL, [ + "tls:", + " certificates:", + " - certFile: /storage/certificates/{$domain}/fullchain.pem", + " keyFile: /storage/certificates/{$domain}/privkey.pem" + ]); + + // Save configuration into Traefik using our new cert files + if (!\file_put_contents(APP_STORAGE_CONFIG . '/' . $domain . '.yml', $config)) { + throw new Exception('Failed to save Traefik configuration.'); + } + + $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; + $certData = openssl_x509_parse(file_get_contents($certPath)); + $validTo = $certData['validTo_time_t'] ?? null; + $dt = (new \DateTime())->setTimestamp($validTo); + return DateTime::addSeconds($dt, -60 * 60 * 24 * 30); + } + + public function isRenewRequired(string $domain, Log $log): bool + { + $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; + if (\file_exists($certPath)) { + $certData = openssl_x509_parse(file_get_contents($certPath)); + $validTo = $certData['validTo_time_t'] ?? 0; + + if (empty($validTo)) { + $log->addTag('certificateDomain', $domain); + throw new Exception('Unable to read certificate file (cert.pem).'); + } + + // LetsEncrypt allows renewal 30 days before expiry + $expiryInAdvance = (60 * 60 * 24 * 30); + if ($validTo - $expiryInAdvance > \time()) { + $log->addTag('certificateDomain', $domain); + $log->addExtra('certificateData', \is_array($certData) ? \json_encode($certData) : \strval($certData)); + return false; + } + } + + return true; + } + + public function deleteCertificate(string $domain): void + { + $directory = APP_STORAGE_CERTIFICATES . '/' . $domain; + $checkTraversal = realpath($directory) === $directory; + + if ($checkTraversal && is_dir($directory)) { + // Delete files, so Traefik is aware of change + array_map('unlink', glob($directory . '/*.*')); + rmdir($directory); + Console::info("Deleted certificate files for {$domain}"); + } else { + Console::info("No certificate files found for {$domain}"); + } + } +} diff --git a/src/Appwrite/Event/Audit.php b/src/Appwrite/Event/Audit.php index 17506bfe6c..6c2a9c3086 100644 --- a/src/Appwrite/Event/Audit.php +++ b/src/Appwrite/Event/Audit.php @@ -2,8 +2,7 @@ namespace Appwrite\Event; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; class Audit extends Event { @@ -11,10 +10,11 @@ class Audit extends Event protected string $mode = ''; protected string $userAgent = ''; protected string $ip = ''; + protected string $hostname = ''; - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { - parent::__construct($connection); + parent::__construct($publisher); $this ->setQueue(Event::AUDITS_QUEUE_NAME) @@ -114,20 +114,37 @@ class Audit extends Event } /** - * Executes the event and sends it to the audit worker. + * Set the hostname. * - * @return string|bool - * @throws \InvalidArgumentException + * @param string $hostname + * + * @return self */ - public function trigger(): string|bool + public function setHostname(string $hostname): self { - if ($this->paused) { - return false; - } + $this->hostname = $hostname; - $client = new Client($this->queue, $this->connection); + return $this; + } - return $client->enqueue([ + /** + * Get the hostname. + * + * @return string + */ + public function getHostname(): string + { + return $this->hostname; + } + + /** + * Prepare payload for queue. + * + * @return array + */ + protected function preparePayload(): array + { + return [ 'project' => $this->project, 'user' => $this->user, 'payload' => $this->payload, @@ -136,6 +153,7 @@ class Audit extends Event 'ip' => $this->ip, 'userAgent' => $this->userAgent, 'event' => $this->event, - ]); + 'hostname' => $this->hostname + ]; } } diff --git a/src/Appwrite/Event/Build.php b/src/Appwrite/Event/Build.php index 1fbf20a9f9..9ea163174f 100644 --- a/src/Appwrite/Event/Build.php +++ b/src/Appwrite/Event/Build.php @@ -3,8 +3,7 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; class Build extends Event { @@ -13,9 +12,9 @@ class Build extends Event protected ?Document $deployment = null; protected ?Document $template = null; - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { - parent::__construct($connection); + parent::__construct($publisher); $this ->setQueue(Event::BUILDS_QUEUE_NAME) @@ -105,26 +104,19 @@ class Build extends Event } /** - * Executes the function event and sends it to the functions worker. + * Prepare payload for queue. * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'resource' => $this->resource, 'deployment' => $this->deployment, 'type' => $this->type, 'template' => $this->template - ]); + ]; } /** diff --git a/src/Appwrite/Event/Certificate.php b/src/Appwrite/Event/Certificate.php index 5d30c3d5ac..827472ae37 100644 --- a/src/Appwrite/Event/Certificate.php +++ b/src/Appwrite/Event/Certificate.php @@ -3,17 +3,16 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; class Certificate extends Event { protected bool $skipRenewCheck = false; protected ?Document $domain = null; - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { - parent::__construct($connection); + parent::__construct($publisher); $this ->setQueue(Event::CERTIFICATES_QUEUE_NAME) @@ -67,23 +66,16 @@ class Certificate extends Event } /** - * Executes the event and sends it to the certificates worker. + * Prepare the payload for the event * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'domain' => $this->domain, 'skipRenewCheck' => $this->skipRenewCheck - ]); + ]; } } diff --git a/src/Appwrite/Event/Database.php b/src/Appwrite/Event/Database.php index 1b0ea6851c..d2f70dddf2 100644 --- a/src/Appwrite/Event/Database.php +++ b/src/Appwrite/Event/Database.php @@ -4,8 +4,7 @@ namespace Appwrite\Event; use Utopia\Database\Document; use Utopia\DSN\DSN; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; class Database extends Event { @@ -14,9 +13,9 @@ class Database extends Event protected ?Document $collection = null; protected ?Document $document = null; - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { - parent::__construct($connection); + parent::__construct($publisher); $this->setClass(Event::DATABASE_CLASS_NAME); } @@ -100,18 +99,8 @@ class Database extends Event return $this->document; } - /** - * Executes the event and send it to the database worker. - * - * @return string|bool - * @throws \InvalidArgumentException - */ - public function trigger(): string|bool + public function getQueue(): string { - if ($this->paused) { - return false; - } - try { $dsn = new DSN($this->getProject()->getAttribute('database')); } catch (\InvalidArgumentException) { @@ -119,23 +108,25 @@ class Database extends Event $dsn = new DSN('mysql://' . $this->getProject()->getAttribute('database')); } - $this->setQueue($dsn->getHost()); + $this->queue = $dsn->getHost(); + return $this->queue; + } - $client = new Client($this->queue, $this->connection); - - try { - $result = $client->enqueue([ - 'project' => $this->project, - 'user' => $this->user, - 'type' => $this->type, - 'collection' => $this->collection, - 'document' => $this->document, - 'database' => $this->database, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) - ]); - return $result; - } catch (\Throwable $th) { - return false; - } + /** + * Prepare the payload for the event + * + * @return array + */ + protected function preparePayload(): array + { + return [ + 'project' => $this->project, + 'user' => $this->user, + 'type' => $this->type, + 'collection' => $this->collection, + 'document' => $this->document, + 'database' => $this->database, + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) + ]; } } diff --git a/src/Appwrite/Event/Delete.php b/src/Appwrite/Event/Delete.php index 1a4c9318e3..450be306d7 100644 --- a/src/Appwrite/Event/Delete.php +++ b/src/Appwrite/Event/Delete.php @@ -3,8 +3,7 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; class Delete extends Event { @@ -16,9 +15,9 @@ class Delete extends Event protected ?string $hourlyUsageRetentionDatetime = null; - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { - parent::__construct($connection); + parent::__construct($publisher); $this ->setQueue(Event::DELETE_QUEUE_NAME) @@ -131,22 +130,14 @@ class Delete extends Event return $this->document; } - /** - * Executes this event and sends it to the deletes worker. + * Prepare the payload for the event * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'type' => $this->type, 'document' => $this->document, @@ -154,6 +145,6 @@ class Delete extends Event 'resourceType' => $this->resourceType, 'datetime' => $this->datetime, 'hourlyUsageRetentionDatetime' => $this->hourlyUsageRetentionDatetime - ]); + ]; } } diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index e3a2e394cf..0edffdf4dc 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -4,8 +4,8 @@ namespace Appwrite\Event; use InvalidArgumentException; use Utopia\Database\Document; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; +use Utopia\Queue\Queue; class Event { @@ -24,11 +24,22 @@ class Event public const FUNCTIONS_QUEUE_NAME = 'v1-functions'; public const FUNCTIONS_CLASS_NAME = 'FunctionsV1'; + /** remove */ public const USAGE_QUEUE_NAME = 'v1-usage'; public const USAGE_CLASS_NAME = 'UsageV1'; public const USAGE_DUMP_QUEUE_NAME = 'v1-usage-dump'; public const USAGE_DUMP_CLASS_NAME = 'UsageDumpV1'; + /** /remove */ + + public const STATS_RESOURCES_QUEUE_NAME = 'v1-stats-resources'; + public const STATS_RESOURCES_CLASS_NAME = 'StatsResourcesV1'; + + public const STATS_USAGE_QUEUE_NAME = 'v1-stats-usage'; + public const STATS_USAGE_CLASS_NAME = 'StatsUsageV1'; + + public const STATS_USAGE_DUMP_QUEUE_NAME = 'v1-stats-usage-dump'; + public const STATS_USAGE_DUMP_CLASS_NAME = 'StatsUsageDumpV1'; public const WEBHOOK_QUEUE_NAME = 'v1-webhooks'; public const WEBHOOK_CLASS_NAME = 'WebhooksV1'; @@ -58,10 +69,10 @@ class Event protected bool $paused = false; /** - * @param Connection $connection + * @param Publisher $publisher * @return void */ - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { } @@ -137,7 +148,6 @@ class Event public function setProject(Document $project): self { $this->project = $project; - return $this; } @@ -312,6 +322,27 @@ class Event return $this->params; } + /** + * Get trimmed values for sensitive/large payload fields. + * Override this method in child classes to add more fields to trim. + * + * @return array + */ + protected function trimPayload(): array + { + $trimmed = []; + + if ($this->project) { + $trimmed['project'] = new Document([ + '$id' => $this->project->getId(), + '$internalId' => $this->project->getInternalId(), + 'database' => $this->project->getAttribute('database') + ]); + } + + return $trimmed; + } + /** * Execute Event. * @@ -324,16 +355,29 @@ class Event return false; } - $client = new Client($this->queue, $this->connection); + /** The getter is required since events like Databases need to override the queue name depending on the project */ + $queue = new Queue($this->getQueue()); - return $client->enqueue([ + // Merge the base payload with any trimmed values + $payload = array_merge($this->preparePayload(), $this->trimPayload()); + return $this->publisher->enqueue($queue, $payload); + } + + /** + * Prepare payload for queue. Can be overridden by child classes to customize payload. + * + * @return array + */ + protected function preparePayload(): array + { + return [ 'project' => $this->project, 'user' => $this->user, 'userId' => $this->userId, 'payload' => $this->payload, 'context' => $this->context, 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) - ]); + ]; } /** diff --git a/src/Appwrite/Event/Func.php b/src/Appwrite/Event/Func.php index 0ad639a9f5..ae316c84e5 100644 --- a/src/Appwrite/Event/Func.php +++ b/src/Appwrite/Event/Func.php @@ -3,8 +3,7 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; class Func extends Event { @@ -20,9 +19,9 @@ class Func extends Event protected ?Document $function = null; protected ?Document $execution = null; - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { - parent::__construct($connection); + parent::__construct($publisher); $this ->setQueue(Event::FUNCTIONS_QUEUE_NAME) @@ -173,13 +172,13 @@ class Func extends Event } /** - * Returns set custom data for the function event. + * Returns set JWT for the function event. * * @return string */ - public function getData(): string + public function getJWT(): string { - return $this->data; + return $this->jwt; } /** @@ -191,37 +190,19 @@ class Func extends Event public function setJWT(string $jwt): self { $this->jwt = $jwt; - return $this; } /** - * Returns set JWT for the function event. + * Prepare payload for the function event. * - * @return string + * @return array */ - public function getJWT(): string + protected function preparePayload(): array { - return $this->jwt; - } - - /** - * Executes the function event and sends it to the functions worker. - * - * @return string|bool - * @throws \InvalidArgumentException - */ - public function trigger(): string|bool - { - if ($this->paused) { - return false; - } - - $client = new Client($this->queue, $this->connection); - $events = $this->getEvent() ? Event::generateEvents($this->getEvent(), $this->getParams()) : null; - return $client->enqueue([ + return [ 'project' => $this->project, 'user' => $this->user, 'userId' => $this->userId, @@ -236,6 +217,6 @@ class Func extends Event 'path' => $this->path, 'headers' => $this->headers, 'method' => $this->method, - ]); + ]; } } diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index a0fca75688..87312182ea 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -2,8 +2,7 @@ namespace Appwrite\Event; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; class Mail extends Event { @@ -16,9 +15,9 @@ class Mail extends Event protected string $bodyTemplate = ''; protected array $attachment = []; - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { - parent::__construct($connection); + parent::__construct($publisher); $this ->setQueue(Event::MAILS_QUEUE_NAME) @@ -397,20 +396,13 @@ class Mail extends Event } /** - * Executes the event and sends it to the mails worker. + * Prepare the payload for the event * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'recipient' => $this->recipient, 'name' => $this->name, @@ -421,6 +413,6 @@ class Mail extends Event 'variables' => $this->variables, 'attachment' => $this->attachment, 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) - ]); + ]; } } diff --git a/src/Appwrite/Event/Messaging.php b/src/Appwrite/Event/Messaging.php index ab9b1bee6b..3ddbac1040 100644 --- a/src/Appwrite/Event/Messaging.php +++ b/src/Appwrite/Event/Messaging.php @@ -3,8 +3,7 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; class Messaging extends Event { @@ -15,9 +14,9 @@ class Messaging extends Event protected ?string $scheduledAt = null; protected ?string $providerType = null; - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { - parent::__construct($connection); + parent::__construct($publisher); $this ->setQueue(Event::MESSAGING_QUEUE_NAME) @@ -27,7 +26,7 @@ class Messaging extends Event /** * Sets type for the build event. * - * @param string $type Can be `MESSAGE_TYPE_INTERNAL` or `MESSAGE_TYPE_EXTERNAL`. + * @param string $type Can be `MESSAGE_SEND_TYPE_INTERNAL` or `MESSAGE_SEND_TYPE_EXTERNAL`. * @return self */ public function setType(string $type): self @@ -176,19 +175,13 @@ class Messaging extends Event } /** - * Executes the event and sends it to the messaging worker. - * @return string|bool - * @throws \InvalidArgumentException + * Prepare the payload for the event + * + * @return array */ - public function trigger(): string | bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'type' => $this->type, 'project' => $this->project, 'user' => $this->user, @@ -196,6 +189,6 @@ class Messaging extends Event 'message' => $this->message, 'recipients' => $this->recipients, 'providerType' => $this->providerType, - ]); + ]; } } diff --git a/src/Appwrite/Event/Migration.php b/src/Appwrite/Event/Migration.php index 789b8e2160..bbb8d77c73 100644 --- a/src/Appwrite/Event/Migration.php +++ b/src/Appwrite/Event/Migration.php @@ -3,17 +3,16 @@ namespace Appwrite\Event; use Utopia\Database\Document; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; class Migration extends Event { protected string $type = ''; protected ?Document $migration = null; - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { - parent::__construct($connection); + parent::__construct($publisher); $this ->setQueue(Event::MIGRATIONS_QUEUE_NAME) @@ -68,23 +67,16 @@ class Migration extends Event } /** - * Executes the migration event and sends it to the migrations worker. + * Prepare the payload for the migration event. * - * @return string|bool - * @throws \InvalidArgumentException + * @return array */ - public function trigger(): string|bool + protected function preparePayload(): array { - if ($this->paused) { - return false; - } - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ + return [ 'project' => $this->project, 'user' => $this->user, 'migration' => $this->migration, - ]); + ]; } } diff --git a/src/Appwrite/Event/Realtime.php b/src/Appwrite/Event/Realtime.php index f4f00b59d4..e6640e70f1 100644 --- a/src/Appwrite/Event/Realtime.php +++ b/src/Appwrite/Event/Realtime.php @@ -7,10 +7,17 @@ use Utopia\Database\Document; class Realtime extends Event { + protected array $subscribers = []; + public function __construct() { } + /** + * Get Realtime payload for this event. + * + * @return array + */ public function getRealtimePayload(): array { $payload = []; @@ -24,6 +31,28 @@ class Realtime extends Event return $payload; } + /** + * Set subscribers for this realtime event. + * + * @param array $subscribers + * @return self + */ + public function setSubscribers(array $subscribers): self + { + $this->subscribers = $subscribers; + return $this; + } + + /** + * Get subscribers for this realtime event. + * + * @return array + */ + public function getSubscribers(): array + { + return $this->subscribers; + } + /** * Execute Event. * @@ -53,17 +82,23 @@ class Realtime extends Event bucket: $bucket, ); - RealtimeAdapter::send( - projectId: $target['projectId'] ?? $this->getProject()->getId(), - payload: $this->getRealtimePayload(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'], - options: [ - 'permissionsChanged' => $target['permissionsChanged'], - 'userId' => $this->getParam('userId') - ] - ); + $projectIds = !empty($this->getSubscribers()) + ? $this->getSubscribers() + : [$target['projectId'] ?? $this->getProject()->getId()]; + + foreach ($projectIds as $projectId) { + RealtimeAdapter::send( + projectId: $projectId, + payload: $this->getRealtimePayload(), + events: $allEvents, + channels: $target['channels'], + roles: $target['roles'], + options: [ + 'permissionsChanged' => $target['permissionsChanged'], + 'userId' => $this->getParam('userId') + ] + ); + } return true; } diff --git a/src/Appwrite/Event/StatsResources.php b/src/Appwrite/Event/StatsResources.php new file mode 100644 index 0000000000..e7a3df97e0 --- /dev/null +++ b/src/Appwrite/Event/StatsResources.php @@ -0,0 +1,29 @@ +<?php + +namespace Appwrite\Event; + +use Utopia\Queue\Publisher; + +class StatsResources extends Event +{ + public function __construct(protected Publisher $publisher) + { + parent::__construct($publisher); + + $this + ->setQueue(Event::STATS_RESOURCES_QUEUE_NAME) + ->setClass(Event::STATS_RESOURCES_CLASS_NAME); + } + + /** + * Prepare the payload for the usage event. + * + * @return array + */ + protected function preparePayload(): array + { + return [ + 'project' => $this->project + ]; + } +} diff --git a/src/Appwrite/Event/StatsUsage.php b/src/Appwrite/Event/StatsUsage.php new file mode 100644 index 0000000000..e259ba5e04 --- /dev/null +++ b/src/Appwrite/Event/StatsUsage.php @@ -0,0 +1,86 @@ +<?php + +namespace Appwrite\Event; + +use Utopia\Database\Document; +use Utopia\Queue\Publisher; + +class StatsUsage extends Event +{ + protected array $metrics = []; + protected array $reduce = []; + protected array $disabled = []; + + public function __construct(protected Publisher $publisher) + { + parent::__construct($publisher); + + $this + ->setQueue(Event::STATS_USAGE_QUEUE_NAME) + ->setClass(Event::STATS_USAGE_CLASS_NAME); + } + + /** + * Add reduce. + * + * @param Document $document + * @return self + */ + public function addReduce(Document $document): self + { + $this->reduce[] = $document; + + return $this; + } + + /** + * Add metric. + * + * @param string $key + * @param int $value + * @return self + */ + public function addMetric(string $key, int $value): self + { + $this->metrics[] = [ + 'key' => $key, + 'value' => $value, + ]; + + return $this; + } + + /** + * Set disabled metrics. + * + * @param string $key + * @return self + */ + public function disableMetric(string $key): self + { + $this->disabled[] = $key; + + return $this; + } + + /** + * Prepare the payload for the event + * + * @return array + */ + protected function preparePayload(): array + { + return [ + 'project' => $this->getProject(), + 'reduce' => $this->reduce, + 'metrics' => \array_filter($this->metrics, function ($metric) { + foreach ($this->disabled as $disabledMetric) { + if (\str_ends_with($metric['key'], $disabledMetric)) { + return false; + } + } + return true; + }), + ]; + } +} diff --git a/src/Appwrite/Event/StatsUsageDump.php b/src/Appwrite/Event/StatsUsageDump.php new file mode 100644 index 0000000000..0573a88040 --- /dev/null +++ b/src/Appwrite/Event/StatsUsageDump.php @@ -0,0 +1,44 @@ +<?php + +namespace Appwrite\Event; + +use Utopia\Queue\Publisher; + +class StatsUsageDump extends Event +{ + protected array $stats; + + public function __construct(protected Publisher $publisher) + { + parent::__construct($publisher); + + $this + ->setQueue(Event::STATS_USAGE_DUMP_QUEUE_NAME) + ->setClass(Event::STATS_USAGE_DUMP_CLASS_NAME); + } + + /** + * Add Stats. + * + * @param array $stats + * @return self + */ + public function setStats(array $stats): self + { + $this->stats = $stats; + + return $this; + } + + /** + * Prepare the payload for the usage dump event. + * + * @return array + */ + protected function preparePayload(): array + { + return [ + 'stats' => $this->stats, + ]; + } +} diff --git a/src/Appwrite/Event/Usage.php b/src/Appwrite/Event/Usage.php deleted file mode 100644 index 161c251c8e..0000000000 --- a/src/Appwrite/Event/Usage.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -namespace Appwrite\Event; - -use Utopia\Database\Document; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; - -class Usage extends Event -{ - protected array $metrics = []; - protected array $reduce = []; - - public function __construct(protected Connection $connection) - { - parent::__construct($connection); - - $this - ->setQueue(Event::USAGE_QUEUE_NAME) - ->setClass(Event::USAGE_CLASS_NAME); - } - - /** - * Add reduce. - * - * @param Document $document - * @return self - */ - public function addReduce(Document $document): self - { - $this->reduce[] = $document; - - return $this; - } - - /** - * Add metric. - * - * @param string $key - * @param int $value - * @return self - */ - public function addMetric(string $key, int $value): self - { - $this->metrics[] = [ - 'key' => $key, - 'value' => $value, - ]; - - return $this; - } - - /** - * Sends metrics to the usage worker. - * - * @return string|bool - */ - public function trigger(): string|bool - { - if ($this->paused) { - return false; - } - - $client = new Client($this->queue, $this->connection); - return $client->enqueue([ - 'project' => $this->getProject(), - 'reduce' => $this->reduce, - 'metrics' => $this->metrics, - ]); - } -} diff --git a/src/Appwrite/Event/UsageDump.php b/src/Appwrite/Event/UsageDump.php deleted file mode 100644 index 2998e4e104..0000000000 --- a/src/Appwrite/Event/UsageDump.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -namespace Appwrite\Event; - -use Utopia\Queue\Client; -use Utopia\Queue\Connection; - -class UsageDump extends Event -{ - protected array $stats; - - public function __construct(protected Connection $connection) - { - parent::__construct($connection); - - $this - ->setQueue(Event::USAGE_DUMP_QUEUE_NAME) - ->setClass(Event::USAGE_DUMP_CLASS_NAME); - } - - /** - * Add Stats. - * - * @param array $stats - * @return self - */ - public function setStats(array $stats): self - { - $this->stats = $stats; - - return $this; - } - - /** - * Sends metrics to the usage worker. - * - * @return string|bool - */ - public function trigger(): string|bool - { - if ($this->paused) { - return false; - } - - $client = new Client($this->queue, $this->connection); - - return $client->enqueue([ - 'stats' => $this->stats, - ]); - } -} diff --git a/src/Appwrite/Event/Webhook.php b/src/Appwrite/Event/Webhook.php index 125c9a78d5..5cc65758ee 100644 --- a/src/Appwrite/Event/Webhook.php +++ b/src/Appwrite/Event/Webhook.php @@ -2,16 +2,30 @@ namespace Appwrite\Event; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; class Webhook extends Event { - public function __construct(protected Connection $connection) + public function __construct(protected Publisher $publisher) { - parent::__construct($connection); + parent::__construct($publisher); $this ->setQueue(Event::WEBHOOK_QUEUE_NAME) ->setClass(Event::WEBHOOK_CLASS_NAME); } + + /** + * Trim the payload for the webhook event. + * + * @return array + */ + public function trimPayload(): array + { + $trimmed = parent::trimPayload(); + if (isset($this->context)) { + $trimmed['context'] = []; + } + return $trimmed; + } } diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 54bf6d96ea..f8f7b9ac6c 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -112,13 +112,15 @@ class Exception extends \Exception /** Teams */ public const TEAM_NOT_FOUND = 'team_not_found'; - public const TEAM_INVITE_ALREADY_EXISTS = 'team_invite_already_exists'; public const TEAM_INVITE_NOT_FOUND = 'team_invite_not_found'; public const TEAM_INVALID_SECRET = 'team_invalid_secret'; public const TEAM_MEMBERSHIP_MISMATCH = 'team_membership_mismatch'; public const TEAM_INVITE_MISMATCH = 'team_invite_mismatch'; public const TEAM_ALREADY_EXISTS = 'team_already_exists'; + /** Console */ + public const RESOURCE_ALREADY_EXISTS = 'resource_already_exists'; + /** Membership */ public const MEMBERSHIP_NOT_FOUND = 'membership_not_found'; public const MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed'; @@ -152,12 +154,18 @@ class Exception extends \Exception public const PROVIDER_CONTRIBUTION_CONFLICT = 'provider_contribution_conflict'; public const GENERAL_PROVIDER_FAILURE = 'general_provider_failure'; + /** Sites */ + public const SITE_NOT_FOUND = 'site_not_found'; + public const SITE_TEMPLATE_NOT_FOUND = 'site_template_not_found'; + /** Functions */ public const FUNCTION_NOT_FOUND = 'function_not_found'; public const FUNCTION_RUNTIME_UNSUPPORTED = 'function_runtime_unsupported'; public const FUNCTION_ENTRYPOINT_MISSING = 'function_entrypoint_missing'; public const FUNCTION_SYNCHRONOUS_TIMEOUT = 'function_synchronous_timeout'; public const FUNCTION_TEMPLATE_NOT_FOUND = 'function_template_not_found'; + public const FUNCTION_RUNTIME_NOT_DETECTED = 'function_runtime_not_detected'; + public const FUNCTION_EXECUTE_PERMISSION_MISSING = 'function_execute_permission_missing'; /** Deployments */ public const DEPLOYMENT_NOT_FOUND = 'deployment_not_found'; @@ -167,11 +175,16 @@ class Exception extends \Exception public const BUILD_NOT_READY = 'build_not_ready'; public const BUILD_IN_PROGRESS = 'build_in_progress'; public const BUILD_ALREADY_COMPLETED = 'build_already_completed'; + public const BUILD_CANCELED = 'build_canceled'; + public const BUILD_FAILED = 'build_failed'; /** Execution */ public const EXECUTION_NOT_FOUND = 'execution_not_found'; public const EXECUTION_IN_PROGRESS = 'execution_in_progress'; + /** Log */ + public const LOG_NOT_FOUND = 'log_not_found'; + /** Databases */ public const DATABASE_NOT_FOUND = 'database_not_found'; public const DATABASE_ALREADY_EXISTS = 'database_already_exists'; @@ -211,6 +224,7 @@ class Exception extends \Exception public const INDEX_LIMIT_EXCEEDED = 'index_limit_exceeded'; public const INDEX_ALREADY_EXISTS = 'index_already_exists'; public const INDEX_INVALID = 'index_invalid'; + public const INDEX_DEPENDENCY = 'index_dependency'; /** Projects */ public const PROJECT_NOT_FOUND = 'project_not_found'; @@ -247,6 +261,7 @@ class Exception extends \Exception /** Variables */ public const VARIABLE_NOT_FOUND = 'variable_not_found'; public const VARIABLE_ALREADY_EXISTS = 'variable_already_exists'; + public const VARIABLE_CANNOT_UNSET_SECRET = 'variable_cannot_unset_secret'; /** Platform */ public const PLATFORM_NOT_FOUND = 'platform_not_found'; @@ -307,11 +322,14 @@ class Exception extends \Exception protected string $type = ''; protected array $errors = []; protected bool $publish; + private array $ctas = []; + private ?string $view = null; - public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int|string $code = null, \Throwable $previous = null) + public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int|string $code = null, \Throwable $previous = null, ?string $view = null) { $this->errors = Config::getParam('errors'); $this->type = $type; + $this->view = $view; $this->code = $code ?? $this->errors[$type]['code']; // Mark string errors like HY001 from PDO as 500 errors @@ -361,4 +379,23 @@ class Exception extends \Exception { return $this->publish; } + + public function addCTA(string $label, ?string $url = null): self + { + $this->ctas[] = [ + 'label' => $label, + 'url' => $url + ]; + return $this; + } + + public function getCTAs(): array + { + return $this->ctas; + } + + public function getView(): ?string + { + return $this->view; + } } diff --git a/src/Appwrite/GraphQL/Schema.php b/src/Appwrite/GraphQL/Schema.php index 833ea9d032..a0d93de45c 100644 --- a/src/Appwrite/GraphQL/Schema.php +++ b/src/Appwrite/GraphQL/Schema.php @@ -98,27 +98,36 @@ class Schema foreach ($routes as $route) { /** @var Route $route */ - $namespace = $route->getLabel('sdk.namespace', ''); - $method = $route->getLabel('sdk.method', ''); - $name = $namespace . \ucfirst($method); + /** @var \Appwrite\SDK\Method $sdk */ + $sdk = $route->getLabel('sdk', false); - if (empty($name)) { + if (empty($sdk)) { continue; } - foreach (Mapper::route($utopia, $route, $complexity) as $field) { - switch ($route->getMethod()) { - case 'GET': - $queries[$name] = $field; - break; - case 'POST': - case 'PUT': - case 'PATCH': - case 'DELETE': - $mutations[$name] = $field; - break; - default: - throw new \Exception("Unsupported method: {$route->getMethod()}"); + if (!\is_array($sdk)) { + $sdk = [$sdk]; + } + + foreach ($sdk as $method) { + $namespace = $method->getNamespace(); + $methodName = $method->getMethodName(); + $name = $namespace . \ucfirst($methodName); + + foreach (Mapper::route($utopia, $route, $method, $complexity) as $field) { + switch ($route->getMethod()) { + case 'GET': + $queries[$name] = $field; + break; + case 'POST': + case 'PUT': + case 'PATCH': + case 'DELETE': + $mutations[$name] = $field; + break; + default: + throw new \Exception("Unsupported method: {$route->getMethod()}"); + } } } } diff --git a/src/Appwrite/GraphQL/Types/Mapper.php b/src/Appwrite/GraphQL/Types/Mapper.php index d8f1d7da09..e5056d0abc 100644 --- a/src/Appwrite/GraphQL/Types/Mapper.php +++ b/src/Appwrite/GraphQL/Types/Mapper.php @@ -4,6 +4,7 @@ namespace Appwrite\GraphQL\Types; use Appwrite\GraphQL\Resolvers; use Appwrite\GraphQL\Types; +use Appwrite\SDK\Method; use Exception; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; @@ -78,6 +79,7 @@ class Mapper public static function route( App $utopia, Route $route, + Method $method, callable $complexity ): iterable { foreach (self::$blacklist as $blacklist) { @@ -86,10 +88,27 @@ class Mapper } } - $names = $route->getLabel('sdk.response.model', 'none'); - $models = \is_array($names) - ? \array_map(static fn ($m) => static::$models[$m], $names) - : [static::$models[$names]]; + $responses = $method->getResponses() ?? []; + + // If responses is an array, map each response to its model + if (\is_array($responses)) { + $models = []; + foreach ($responses as $response) { + $modelName = $response->getModel(); + + if (\is_array($modelName)) { + foreach ($modelName as $name) { + $models[] = static::$models[$name]; + } + } else { + $models[] = static::$models[$modelName]; + } + } + } else { + // If single response, get its model and wrap in array + $modelName = $responses->getModel(); + $models = [static::$models[$modelName]]; + } foreach ($models as $model) { $type = Mapper::model(\ucfirst($model->getType())); @@ -98,13 +117,25 @@ class Mapper $list = false; foreach ($route->getParams() as $name => $parameter) { + $methodParameters = $method->getParameters(); + + if (!empty($methodParameters)) { + if (!array_key_exists($name, $methodParameters)) { + continue; + } + $optional = $methodParameters[$name]['optional']; + } else { + $optional = $parameter['optional']; + } + if ($name === 'queries') { $list = true; } + $parameterType = Mapper::param( $utopia, $parameter['validator'], - !$parameter['optional'], + !$optional, $parameter['injections'] ); $params[$name] = [ diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index dceafacf6e..9b63c4fc11 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -349,6 +349,16 @@ class Realtime extends Adapter $roles = [Role::team($project->getAttribute('teamId'))->toString()]; } + break; + + case 'sites': + if ($parts[2] === 'deployments') { + $channels[] = 'console'; + $channels[] = 'projects.' . $project->getId(); + $projectId = 'console'; + $roles = [Role::team($project->getAttribute('teamId'))->toString()]; + } + break; case 'migrations': $channels[] = 'console'; diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index cee1b2d263..17e93f43f5 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -91,6 +91,9 @@ abstract class Migration '1.5.10' => 'V20', '1.5.11' => 'V20', '1.6.0' => 'V21', + '1.6.1' => 'V21', + '1.6.2' => 'V22', + '1.7.0' => 'V23', ]; /** diff --git a/src/Appwrite/Migration/Version/V19.php b/src/Appwrite/Migration/Version/V19.php index 18234ebdc4..4415003bfd 100644 --- a/src/Appwrite/Migration/Version/V19.php +++ b/src/Appwrite/Migration/Version/V19.php @@ -10,7 +10,6 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception; use Utopia\Database\Query; -use Utopia\System\System; class V19 extends Migration { @@ -731,7 +730,7 @@ class V19 extends Migration if (empty($document->getAttribute('scheduleId', null))) { $schedule = $this->consoleDB->createDocument('schedules', new Document([ - 'region' => System::getEnv('_APP_REGION', 'default'), // Todo replace with projects region + 'region' => $project->getAttribute('region'), 'resourceType' => 'function', 'resourceId' => $document->getId(), 'resourceInternalId' => $document->getInternalId(), diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index 51e8a18b9d..3f1bc0d228 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -186,7 +186,7 @@ class V21 extends Migration $document->setAttribute('scopes', []); // Add size attribute - $document->setAttribute('specification', APP_FUNCTION_SPECIFICATION_DEFAULT); + $document->setAttribute('specification', APP_COMPUTE_SPECIFICATION_DEFAULT); } return $document; diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php new file mode 100644 index 0000000000..4d15662112 --- /dev/null +++ b/src/Appwrite/Migration/Version/V22.php @@ -0,0 +1,83 @@ +<?php + +namespace Appwrite\Migration\Version; + +use Appwrite\Migration\Migration; +use Exception; +use Throwable; +use Utopia\CLI\Console; +use Utopia\Database\Database; + +class V22 extends Migration +{ + /** + * @throws Throwable + */ + public function execute(): void + { + /** + * Disable SubQueries for Performance. + */ + foreach (['subQueryIndexes', 'subQueryPlatforms', 'subQueryDomains', 'subQueryKeys', 'subQueryWebhooks', 'subQuerySessions', 'subQueryTokens', 'subQueryMemberships', 'subQueryVariables', 'subQueryChallenges', 'subQueryProjectVariables', 'subQueryTargets', 'subQueryTopicTargets'] as $name) { + Database::addFilter( + $name, + fn () => null, + fn () => [] + ); + } + + Console::info('Migrating Collections'); + $this->migrateCollections(); + } + + /** + * Migrate Collections. + * + * @return void + * @throws Exception|Throwable + */ + private function migrateCollections(): void + { + $internalProjectId = $this->project->getInternalId(); + $collectionType = match ($internalProjectId) { + 'console' => 'console', + default => 'projects', + }; + + $collections = $this->collections[$collectionType]; + foreach ($collections as $collection) { + $id = $collection['$id']; + + Console::log("Migrating Collection \"{$id}\""); + + $this->projectDB->setNamespace("_$internalProjectId"); + + switch ($id) { + case 'installations': + // Create personalAccessToken attribute + try { + $this->createAttributeFromCollection($this->projectDB, $id, 'personalAccessToken'); + } catch (Throwable $th) { + Console::warning("'personalAccessToken' from {$id}: {$th->getMessage()}"); + } + + // Create personalAccessTokenExpiry attribute + try { + $this->createAttributeFromCollection($this->projectDB, $id, 'personalAccessTokenExpiry'); + } catch (Throwable $th) { + Console::warning("'personalAccessTokenExpiry' from {$id}: {$th->getMessage()}"); + } + + // Create personalRefreshToken attribute + try { + $this->createAttributeFromCollection($this->projectDB, $id, 'personalRefreshToken'); + } catch (Throwable $th) { + Console::warning("'personalRefreshToken' from {$id}: {$th->getMessage()}"); + } + break; + } + + usleep(50000); + } + } +} diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php new file mode 100644 index 0000000000..dec7e8e9d3 --- /dev/null +++ b/src/Appwrite/Migration/Version/V23.php @@ -0,0 +1,69 @@ +<?php + +namespace Appwrite\Migration\Version; + +use Appwrite\Migration\Migration; +use Exception; +use Throwable; +use Utopia\CLI\Console; +use Utopia\Database\Database; + +class V23 extends Migration +{ + /** + * @throws Throwable + */ + public function execute(): void + { + /** + * Disable SubQueries for Performance. + */ + foreach (['subQueryIndexes', 'subQueryPlatforms', 'subQueryDomains', 'subQueryKeys', 'subQueryWebhooks', 'subQuerySessions', 'subQueryTokens', 'subQueryMemberships', 'subQueryVariables', 'subQueryChallenges', 'subQueryProjectVariables', 'subQueryTargets', 'subQueryTopicTargets'] as $name) { + Database::addFilter( + $name, + fn () => null, + fn () => [] + ); + } + + Console::info('Migrating Collections'); + $this->migrateCollections(); + } + + /** + * Migrate Collections. + * + * @return void + * @throws Exception|Throwable + */ + private function migrateCollections(): void + { + $internalProjectId = $this->project->getInternalId(); + $collectionType = match ($internalProjectId) { + 'console' => 'console', + default => 'projects', + }; + + $collections = $this->collections[$collectionType]; + foreach ($collections as $collection) { + $id = $collection['$id']; + + Console::log("Migrating Collection \"{$id}\""); + + $this->projectDB->setNamespace("_$internalProjectId"); + + switch ($id) { + case 'memberships': + // Create roles index + try { + $this->createIndexFromCollection($this->projectDB, $id, '_key_roles'); + } catch (Throwable $th) { + Console::warning("'_key_roles' from {$id}: {$th->getMessage()}"); + } + break; + } + + usleep(50000); + } + } +} diff --git a/src/Appwrite/Network/Validator/CNAME.php b/src/Appwrite/Network/Validator/DNS.php similarity index 53% rename from src/Appwrite/Network/Validator/CNAME.php rename to src/Appwrite/Network/Validator/DNS.php index e1ae061c84..73494ddc3e 100644 --- a/src/Appwrite/Network/Validator/CNAME.php +++ b/src/Appwrite/Network/Validator/DNS.php @@ -4,24 +4,22 @@ namespace Appwrite\Network\Validator; use Utopia\Validator; -class CNAME extends Validator +class DNS extends Validator { + public const RECORD_A = 'a'; + public const RECORD_AAAA = 'aaaa'; + public const RECORD_CNAME = 'cname'; + /** * @var mixed */ protected mixed $logs; - /** - * @var string - */ - protected $target; - /** * @param string $target */ - public function __construct($target) + public function __construct(protected string $target, protected string $type = self::RECORD_CNAME) { - $this->target = $target; } /** @@ -29,7 +27,7 @@ class CNAME extends Validator */ public function getDescription(): string { - return 'Invalid CNAME record'; + return 'Invalid DNS record'; } /** @@ -41,20 +39,34 @@ class CNAME extends Validator } /** - * Check if CNAME record target value matches selected target + * Check if DNS record value matches specific value * * @param mixed $domain * * @return bool */ - public function isValid($domain): bool + public function isValid($value): bool { - if (!is_string($domain)) { + $typeNative = match ($this->type) { + self::RECORD_A => DNS_A, + self::RECORD_AAAA => DNS_AAAA, + self::RECORD_CNAME => DNS_CNAME, + default => throw new \Exception('Record type not supported.') + }; + + $dnsKey = match ($this->type) { + self::RECORD_A => 'ip', + self::RECORD_AAAA => 'ipv6', + self::RECORD_CNAME => 'target', + default => throw new \Exception('Record type not supported.') + }; + + if (!is_string($value)) { return false; } try { - $records = \dns_get_record($domain, DNS_CNAME); + $records = \dns_get_record($value, $typeNative); $this->logs = $records; } catch (\Throwable $th) { return false; @@ -65,7 +77,7 @@ class CNAME extends Validator } foreach ($records as $record) { - if (isset($record['target']) && $record['target'] === $this->target) { + if (isset($record[$dnsKey]) && $record[$dnsKey] === $this->target) { return true; } } diff --git a/src/Appwrite/Platform/Action.php b/src/Appwrite/Platform/Action.php new file mode 100644 index 0000000000..72c41582ea --- /dev/null +++ b/src/Appwrite/Platform/Action.php @@ -0,0 +1,90 @@ +<?php + +namespace Appwrite\Platform; + +use Swoole\Coroutine as Co; +use Utopia\Database\Database; +use Utopia\Database\Query; +use Utopia\Platform\Action as UtopiaAction; + +class Action extends UtopiaAction +{ + /** + * Log Error Callback + * + * @var callable + */ + protected mixed $logError; + + /** + * Foreach Document + * Call provided callback for each document in the collection + * + * @param string $projectId + * @param string $collection + * @param array $queries + * @param callable $callback + * + * @return void + */ + protected function foreachDocument(Database $database, string $collection, array $queries = [], callable $callback = null, int $limit = 1000, bool $concurrent = false): void + { + $results = []; + $sum = $limit; + $latestDocument = null; + + while ($sum === $limit) { + $newQueries = $queries; + try { + if ($latestDocument !== null) { + array_unshift($newQueries, Query::cursorAfter($latestDocument)); + } + $newQueries[] = Query::limit($limit); + $database->disableValidation(); + $results = $database->find($collection, $newQueries); + $database->enableValidation(); + } catch (\Exception $e) { + if (!empty($this->logError)) { + call_user_func_array($this->logError, [$e, "CLI", "fetch_documents_namespace_{$database->getNamespace()}_collection{$collection}"]); + } + } + + if (empty($results)) { + return; + } + + $sum = count($results); + + if ($concurrent) { + $callables = []; + $errors = []; + + foreach ($results as $document) { + if (is_callable($callback)) { + $callables[] = Co\go(function () use ($document, $callback, &$errors) { + try { + $callback($document); + } catch (\Throwable $error) { + $errors[] = $error; + } + }); + } + } + + Co::join($callables); + + if (!empty($errors)) { + throw new \Error("Errors found in concurrent foreachDocument: " . \json_encode($errors)); + } + } else { + foreach ($results as $document) { + if (is_callable($callback)) { + $callback($document); + } + } + } + + $latestDocument = $results[array_key_last($results)]; + } + } +} diff --git a/src/Appwrite/Platform/Appwrite.php b/src/Appwrite/Platform/Appwrite.php index 6b3eb077fa..be6ddbae8a 100644 --- a/src/Appwrite/Platform/Appwrite.php +++ b/src/Appwrite/Platform/Appwrite.php @@ -2,7 +2,11 @@ namespace Appwrite\Platform; +use Appwrite\Platform\Modules\Console; use Appwrite\Platform\Modules\Core; +use Appwrite\Platform\Modules\Functions; +use Appwrite\Platform\Modules\Proxy; +use Appwrite\Platform\Modules\Sites; use Utopia\Platform\Platform; class Appwrite extends Platform @@ -10,5 +14,9 @@ class Appwrite extends Platform public function __construct() { parent::__construct(new Core()); + $this->addModule(new Functions\Module()); + $this->addModule(new Sites\Module()); + $this->addModule(new Console\Module()); + $this->addModule(new Proxy\Module()); } } diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php new file mode 100644 index 0000000000..542b29bcd5 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -0,0 +1,274 @@ +<?php + +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; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; +use Utopia\Platform\Action; +use Utopia\Swoole\Request; +use Utopia\System\System; +use Utopia\VCS\Adapter\Git\GitHub; +use Utopia\VCS\Exception\RepositoryNotFound; + +class Base extends Action +{ + public function redeployVcsFunction(Request $request, Document $function, Document $project, Document $installation, Database $dbForProject, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, string $referenceType = 'branch', string $reference = ''): Document + { + $deploymentId = ID::unique(); + $entrypoint = $function->getAttribute('entrypoint', ''); + $providerInstallationId = $installation->getAttribute('providerInstallationId', ''); + $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); + $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); + $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); + $owner = $github->getOwnerName($providerInstallationId); + $providerRepositoryId = $function->getAttribute('providerRepositoryId', ''); + try { + $repositoryName = $github->getRepositoryName($providerRepositoryId) ?? ''; + if (empty($repositoryName)) { + throw new Exception(Exception::PROVIDER_REPOSITORY_NOT_FOUND); + } + } catch (RepositoryNotFound $e) { + throw new Exception(Exception::PROVIDER_REPOSITORY_NOT_FOUND); + } + + $commitDetails = []; + $branchUrl = ""; + $providerBranch = ""; + + // TODO: Support tag in future + if ($referenceType === 'branch') { + $providerBranch = empty($reference) ? $function->getAttribute('providerBranch', 'main') : $reference; + $branchUrl = "https://github.com/$owner/$repositoryName/tree/$providerBranch"; + try { + $commitDetails = $github->getLatestCommit($owner, $repositoryName, $providerBranch); + } catch (\Throwable $error) { + // Ignore; deployment can continue + } + } elseif ($referenceType === 'commit') { + try { + $commitDetails = $github->getCommit($owner, $repositoryName, $reference); + } catch (\Throwable $error) { + // Ignore; deployment can continue + } + } + + $repositoryUrl = "https://github.com/$owner/$repositoryName"; + + $deployment = $dbForProject->createDocument('deployments', new Document([ + '$id' => $deploymentId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'resourceId' => $function->getId(), + 'resourceInternalId' => $function->getInternalId(), + 'resourceType' => 'functions', + 'entrypoint' => $entrypoint, + 'buildCommands' => $function->getAttribute('commands', ''), + 'type' => 'vcs', + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getInternalId(), + 'providerRepositoryId' => $providerRepositoryId, + 'repositoryId' => $function->getAttribute('repositoryId', ''), + 'repositoryInternalId' => $function->getAttribute('repositoryInternalId', ''), + 'providerBranchUrl' => $branchUrl, + 'providerRepositoryName' => $repositoryName, + 'providerRepositoryOwner' => $owner, + 'providerRepositoryUrl' => $repositoryUrl, + 'providerCommitHash' => $commitDetails['commitHash'] ?? '', + 'providerCommitAuthorUrl' => $commitDetails['commitAuthorUrl'] ?? '', + 'providerCommitAuthor' => $commitDetails['commitAuthor'] ?? '', + 'providerCommitMessage' => mb_strimwidth($commitDetails['commitMessage'] ?? '', 0, 255, '...'), + 'providerCommitUrl' => $commitDetails['commitUrl'] ?? '', + 'providerBranch' => $providerBranch, + 'providerRootDirectory' => $function->getAttribute('providerRootDirectory', ''), + 'search' => implode(' ', [$deploymentId, $entrypoint]), + 'activate' => $activate, + ])); + + $function = $function + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); + + $queueForBuilds + ->setType(BUILD_TYPE_DEPLOYMENT) + ->setResource($function) + ->setDeployment($deployment) + ->setTemplate($template); + + return $deployment; + } + + public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github, bool $activate, string $referenceType = 'branch', string $reference = ''): Document + { + $deploymentId = ID::unique(); + $providerInstallationId = $installation->getAttribute('providerInstallationId', ''); + $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); + $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); + $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); + $owner = $github->getOwnerName($providerInstallationId); + $providerRepositoryId = $site->getAttribute('providerRepositoryId', ''); + try { + $repositoryName = $github->getRepositoryName($providerRepositoryId) ?? ''; + if (empty($repositoryName)) { + throw new Exception(Exception::PROVIDER_REPOSITORY_NOT_FOUND); + } + } catch (RepositoryNotFound $e) { + throw new Exception(Exception::PROVIDER_REPOSITORY_NOT_FOUND); + } + + $commitDetails = []; + $branchUrl = ""; + $providerBranch = ""; + + // TODO: Support tag in future + if ($referenceType === 'branch') { + $providerBranch = empty($reference) ? $site->getAttribute('providerBranch', 'main') : $reference; + $branchUrl = "https://github.com/$owner/$repositoryName/tree/$providerBranch"; + try { + $commitDetails = $github->getLatestCommit($owner, $repositoryName, $providerBranch); + } catch (\Throwable $error) { + // Ignore; deployment can continue + } + } elseif ($referenceType === 'commit') { + try { + $commitDetails = $github->getCommit($owner, $repositoryName, $reference); + } catch (\Throwable $error) { + // Ignore; deployment can continue + } + } + + $repositoryUrl = "https://github.com/$owner/$repositoryName"; + + $commands = []; + if (!empty($site->getAttribute('installCommand', ''))) { + $commands[] = $site->getAttribute('installCommand', ''); + } + if (!empty($site->getAttribute('buildCommand', ''))) { + $commands[] = $site->getAttribute('buildCommand', ''); + } + + $deployment = $dbForProject->createDocument('deployments', new Document([ + '$id' => $deploymentId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'resourceId' => $site->getId(), + 'resourceInternalId' => $site->getInternalId(), + 'resourceType' => 'sites', + 'buildCommands' => implode(' && ', $commands), + 'buildOutput' => $site->getAttribute('outputDirectory', ''), + 'adapter' => $site->getAttribute('adapter', ''), + 'fallbackFile' => $site->getAttribute('fallbackFile', ''), + 'type' => 'vcs', + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getInternalId(), + 'providerRepositoryId' => $providerRepositoryId, + 'repositoryId' => $site->getAttribute('repositoryId', ''), + 'repositoryInternalId' => $site->getAttribute('repositoryInternalId', ''), + 'providerBranchUrl' => $branchUrl, + 'providerRepositoryName' => $repositoryName, + 'providerRepositoryOwner' => $owner, + 'providerRepositoryUrl' => $repositoryUrl, + 'providerCommitHash' => $commitDetails['commitHash'] ?? '', + 'providerCommitAuthorUrl' => $commitDetails['commitAuthorUrl'] ?? '', + 'providerCommitAuthor' => $commitDetails['commitAuthor'] ?? '', + 'providerCommitMessage' => mb_strimwidth($commitDetails['commitMessage'] ?? '', 0, 255, '...'), + 'providerCommitUrl' => $commitDetails['commitUrl'] ?? '', + 'providerBranch' => $providerBranch, + 'providerRootDirectory' => $site->getAttribute('providerRootDirectory', ''), + 'search' => implode(' ', [$deploymentId]), + 'activate' => $activate, + ])); + + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $domain = ID::unique() . "." . $sitesDomain; + + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); + + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'trigger' => 'deployment', + 'type' => 'deployment', + 'deploymentId' => $deployment->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentResourceType' => 'site', + 'deploymentResourceId' => $site->getId(), + 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentVcsProviderBranch' => $providerBranch, + 'status' => 'verified', + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain]), + 'owner' => 'Appwrite', + 'region' => $project->getAttribute('region') + ])) + ); + + $queueForBuilds + ->setType(BUILD_TYPE_DEPLOYMENT) + ->setResource($site) + ->setDeployment($deployment) + ->setTemplate($template); + + return $deployment; + } + + 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/Functions/Specification.php b/src/Appwrite/Platform/Modules/Compute/Specification.php similarity index 91% rename from src/Appwrite/Functions/Specification.php rename to src/Appwrite/Platform/Modules/Compute/Specification.php index 50a3c02b62..cf48896a7b 100644 --- a/src/Appwrite/Functions/Specification.php +++ b/src/Appwrite/Platform/Modules/Compute/Specification.php @@ -1,6 +1,6 @@ <?php -namespace Appwrite\Functions; +namespace Appwrite\Platform\Modules\Compute; class Specification { diff --git a/src/Appwrite/Functions/Validator/RuntimeSpecification.php b/src/Appwrite/Platform/Modules/Compute/Validator/Specification.php similarity index 88% rename from src/Appwrite/Functions/Validator/RuntimeSpecification.php rename to src/Appwrite/Platform/Modules/Compute/Validator/Specification.php index 22311838f6..770f7b11e0 100644 --- a/src/Appwrite/Functions/Validator/RuntimeSpecification.php +++ b/src/Appwrite/Platform/Modules/Compute/Validator/Specification.php @@ -1,10 +1,10 @@ <?php -namespace Appwrite\Functions\Validator; +namespace Appwrite\Platform\Modules\Compute\Validator; use Utopia\Validator; -class RuntimeSpecification extends Validator +class Specification extends Validator { private array $plan; @@ -35,8 +35,8 @@ class RuntimeSpecification extends Validator foreach ($this->specifications as $size => $values) { if ($values['cpus'] <= $this->maxCpus && $values['memory'] <= $this->maxMemory) { - if (!empty($this->plan) && array_key_exists('runtimeSpecifications', $this->plan)) { - if (!\in_array($size, $this->plan['runtimeSpecifications'])) { + if (!empty($this->plan) && array_key_exists('specifications', $this->plan)) { + if (!\in_array($size, $this->plan['specifications'])) { continue; } } diff --git a/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php new file mode 100644 index 0000000000..ec1c195d61 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Console/Http/Resources/Get.php @@ -0,0 +1,89 @@ +<?php + +namespace Appwrite\Platform\Modules\Console\Http\Resources; + +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Domain; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; + +class Get extends Action +{ + use HTTP; + + public static function getName() + { + return 'getResource'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/console/resources') + ->desc('Check resource ID availability') + ->groups(['api', 'projects']) + ->label('scope', 'rules.read') + ->label('sdk', new Method( + namespace: 'console', + name: 'getResource', + description: <<<EOT + Check if a resource ID is available. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE, + )) + ->label('abuse-limit', 120) + ->label('abuse-key', 'userId:{userId}, url:{url}') + ->label('abuse-time', 60) + ->param('value', '', new Text(256), 'Resource value.') + ->param('type', '', new WhiteList(['rules']), 'Resource type.') + ->inject('response') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action( + string $value, + string $type, + Response $response, + Database $dbForPlatform + ) { + if ($type === 'rules') { + $validator = new Domain($value); + + if (!$validator->isValid($value)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, $validator->getDescription()); + } + + $document = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$value]), + ])); + + if (!$document->isEmpty()) { + throw new Exception(Exception::RESOURCE_ALREADY_EXISTS); + } + + $response->noContent(); + } + + // Only occurs if type is added into whitelist, but not supported in action + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Invalid type'); + } +} diff --git a/src/Appwrite/Platform/Modules/Console/Module.php b/src/Appwrite/Platform/Modules/Console/Module.php new file mode 100644 index 0000000000..7bf2805479 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Console/Module.php @@ -0,0 +1,14 @@ +<?php + +namespace Appwrite\Platform\Modules\Console; + +use Appwrite\Platform\Modules\Console\Services\Http; +use Utopia\Platform; + +class Module extends Platform\Module +{ + public function __construct() + { + $this->addService('http', new Http()); + } +} diff --git a/src/Appwrite/Platform/Modules/Console/Services/Http.php b/src/Appwrite/Platform/Modules/Console/Services/Http.php new file mode 100644 index 0000000000..6221db6a96 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Console/Services/Http.php @@ -0,0 +1,16 @@ +<?php + +namespace Appwrite\Platform\Modules\Console\Services; + +use Appwrite\Platform\Modules\Console\Http\Resources\Get as GetResourceAvailability; +use Utopia\Platform\Service; + +class Http extends Service +{ + public function __construct() + { + $this->type = Service::TYPE_HTTP; + // Resources + $this->addAction(GetResourceAvailability::getName(), new GetResourceAvailability()); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php new file mode 100644 index 0000000000..00c4f402a1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -0,0 +1,305 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Deployments; + +use Appwrite\Event\Build; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Storage\Device; +use Utopia\Storage\Validator\File; +use Utopia\Storage\Validator\FileExt; +use Utopia\Storage\Validator\FileSize; +use Utopia\Storage\Validator\Upload; +use Utopia\Swoole\Request; +use Utopia\System\System; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; + +class Create extends Action +{ + use HTTP; + + public static function getName() + { + return 'createDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/functions/:functionId/deployments') + ->desc('Create deployment') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('event', 'functions.[functionId].deployments.[deploymentId].create') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('audits.event', 'deployment.create') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'createDeployment', + description: <<<EOT + 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. + + This 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). + + Use the "command" param to set the entrypoint used to execute your code. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_DEPLOYMENT, + ) + ], + requestType: 'multipart/form-data', + type: MethodType::UPLOAD, + packaging: true, + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('entrypoint', null, new Text(1028), 'Entrypoint File.', true) + ->param('commands', null, new Text(8192, 0), 'Build Commands.', true) + ->param('code', [], new File(), '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.', skipValidation: true) + ->param('activate', false, new Boolean(true), 'Automatically activate the deployment when it is finished building.') + ->inject('request') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('project') + ->inject('deviceForFunctions') + ->inject('deviceForLocal') + ->inject('queueForBuilds') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + ?string $entrypoint, + ?string $commands, + mixed $code, + mixed $activate, + Request $request, + Response $response, + Database $dbForProject, + Event $queueForEvents, + Document $project, + Device $deviceForFunctions, + Device $deviceForLocal, + Build $queueForBuilds + ) { + $activate = \strval($activate) === 'true' || \strval($activate) === '1'; + + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + if ($entrypoint === null) { + $entrypoint = $function->getAttribute('entrypoint', ''); + } + + if ($commands === null) { + $commands = $function->getAttribute('commands', ''); + } + + if (empty($entrypoint)) { + throw new Exception(Exception::FUNCTION_ENTRYPOINT_MISSING); + } + + $file = $request->getFiles('code'); + + // GraphQL multipart spec adds files with index keys + if (empty($file)) { + $file = $request->getFiles(0); + } + + if (empty($file)) { + throw new Exception(Exception::STORAGE_FILE_EMPTY, 'No file sent'); + } + + $fileExt = new FileExt([FileExt::TYPE_GZIP]); + $fileSizeValidator = new FileSize(System::getEnv('_APP_COMPUTE_SIZE_LIMIT', '30000000')); + $upload = new Upload(); + + // Make sure we handle a single file and multiple files the same way + $fileName = (\is_array($file['name']) && isset($file['name'][0])) ? $file['name'][0] : $file['name']; + $fileTmpName = (\is_array($file['tmp_name']) && isset($file['tmp_name'][0])) ? $file['tmp_name'][0] : $file['tmp_name']; + $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; + + if (!$fileExt->isValid($file['name'])) { // Check if file type is allowed + throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED); + } + + $contentRange = $request->getHeader('content-range'); + $deploymentId = ID::unique(); + $chunk = 1; + $chunks = 1; + + if (!empty($contentRange)) { + $start = $request->getContentRangeStart(); + $end = $request->getContentRangeEnd(); + $fileSize = $request->getContentRangeSize(); + $deploymentId = $request->getHeader('x-appwrite-id', $deploymentId); + // TODO make `end >= $fileSize` in next breaking version + if (is_null($start) || is_null($end) || is_null($fileSize) || $end > $fileSize) { + throw new Exception(Exception::STORAGE_INVALID_CONTENT_RANGE); + } + + // TODO remove the condition that checks `$end === $fileSize` in next breaking version + if ($end === $fileSize - 1 || $end === $fileSize) { + //if it's a last chunks the chunk size might differ, so we set the $chunks and $chunk to notify it's last chunk + $chunks = $chunk = -1; + } else { + // Calculate total number of chunks based on the chunk size i.e ($rangeEnd - $rangeStart) + $chunks = (int) ceil($fileSize / ($end + 1 - $start)); + $chunk = (int) ($start / ($end + 1 - $start)) + 1; + } + } + + if (!$fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit + throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE); + } + + if (!$upload->isValid($fileTmpName)) { + throw new Exception(Exception::STORAGE_INVALID_FILE); + } + + // Save to storage + $fileSize ??= $deviceForLocal->getFileSize($fileTmpName); + $path = $deviceForFunctions->getPath($deploymentId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + + $metadata = ['content_type' => $deviceForLocal->getFileMimeType($fileTmpName)]; + if (!$deployment->isEmpty()) { + $chunks = $deployment->getAttribute('sourceChunksTotal', 1); + $metadata = $deployment->getAttribute('sourceMetadata', []); + if ($chunk === -1) { + $chunk = $chunks; + } + } + + $chunksUploaded = $deviceForFunctions->upload($fileTmpName, $path, $chunk, $chunks, $metadata); + + if (empty($chunksUploaded)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed moving file'); + } + + $type = $request->getHeader('x-sdk-language') === 'cli' ? 'cli' : 'manual'; + + if ($chunksUploaded === $chunks) { + if ($activate) { + // Remove deploy for all other deployments. + $activeDeployments = $dbForProject->find('deployments', [ + Query::equal('activate', [true]), + Query::equal('resourceId', [$functionId]), + Query::equal('resourceType', ['functions']) + ]); + + foreach ($activeDeployments as $activeDeployment) { + $activeDeployment->setAttribute('activate', false); + $dbForProject->updateDocument('deployments', $activeDeployment->getId(), $activeDeployment); + } + } + + $fileSize = $deviceForFunctions->getFileSize($path); + + if ($deployment->isEmpty()) { + $deployment = $dbForProject->createDocument('deployments', new Document([ + '$id' => $deploymentId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'resourceInternalId' => $function->getInternalId(), + 'resourceId' => $function->getId(), + 'resourceType' => 'functions', + 'entrypoint' => $entrypoint, + 'buildCommands' => $commands, + 'sourcePath' => $path, + 'sourceSize' => $fileSize, + 'totalSize' => $fileSize, + 'search' => implode(' ', [$deploymentId, $entrypoint]), + 'activate' => $activate, + 'sourceMetadata' => $metadata, + 'type' => $type + ])); + + $function = $function + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); + } else { + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceSize', $fileSize)->setAttribute('sourceMetadata', $metadata)); + } + + // Start the build + $queueForBuilds + ->setType(BUILD_TYPE_DEPLOYMENT) + ->setResource($function) + ->setDeployment($deployment); + } else { + if ($deployment->isEmpty()) { + $deployment = $dbForProject->createDocument('deployments', new Document([ + '$id' => $deploymentId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'resourceInternalId' => $function->getInternalId(), + 'resourceId' => $function->getId(), + 'resourceType' => 'functions', + 'entrypoint' => $entrypoint, + 'buildCommands' => $commands, + 'sourcePath' => $path, + 'sourceSize' => $fileSize, + 'totalSize' => $fileSize, + 'sourceChunksTotal' => $chunks, + 'sourceChunksUploaded' => $chunksUploaded, + 'search' => implode(' ', [$deploymentId, $entrypoint]), + 'activate' => $activate, + 'sourceMetadata' => $metadata, + 'type' => $type + ])); + + $function = $function + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); + } else { + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceChunksUploaded', $chunksUploaded)->setAttribute('sourceMetadata', $metadata)); + } + } + + $metadata = null; + + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php new file mode 100644 index 0000000000..b66ea30bb2 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php @@ -0,0 +1,135 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Deployments; + +use Appwrite\Event\Delete as DeleteEvent; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +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\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Storage\Device; + +class Delete extends Action +{ + use HTTP; + + public static function getName() + { + return 'deleteDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/functions/:functionId/deployments/:deploymentId') + ->desc('Delete deployment') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('event', 'functions.[functionId].deployments.[deploymentId].delete') + ->label('audits.event', 'deployment.delete') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'deleteDeployment', + description: <<<EOT + Delete a code deployment by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDeletes') + ->inject('queueForEvents') + ->inject('deviceForFunctions') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $deploymentId, + Response $response, + Database $dbForProject, + DeleteEvent $queueForDeletes, + Event $queueForEvents, + Device $deviceForFunctions + ) { + $function = $dbForProject->getDocument('functions', $functionId); + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if ($deployment->getAttribute('resourceId') !== $function->getId()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if (!$dbForProject->deleteDocument('deployments', $deployment->getId())) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from DB'); + } + + if (!empty($deployment->getAttribute('sourcePath', ''))) { + if (!($deviceForFunctions->delete($deployment->getAttribute('sourcePath', '')))) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from storage'); + } + } + + if ($function->getAttribute('latestDeploymentId') === $deployment->getId()) { + $latestDeployment = $dbForProject->findOne('deployments', [ + Query::equal('resourceType', ['functions']), + Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::orderDesc('$createdAt'), + ]); + $function = $dbForProject->updateDocument( + 'functions', + $function->getId(), + $function + ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->isEmpty() ? '' : $latestDeployment->getCreatedAt()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getInternalId()) + ->setAttribute('latestDeploymentId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getId()) + ->setAttribute('latestDeploymentStatus', $latestDeployment->isEmpty() ? '' : $latestDeployment->getAttribute('status', '')) + ); + } + + if ($function->getAttribute('deploymentId') === $deployment->getId()) { // Reset function deployment + $function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [ + 'deploymentId' => '', + 'deploymentInternalId' => '', + 'deploymentCreatedAt' => '', + ]))); + } + + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $queueForDeletes + ->setType(DELETE_TYPE_DOCUMENT) + ->setDocument($deployment); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php new file mode 100644 index 0000000000..94d86a2647 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php @@ -0,0 +1,151 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Download; + +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Storage\Device; +use Utopia\Swoole\Request; +use Utopia\Validator\WhiteList; + +class Get extends Action +{ + use HTTP; + + public static function getName() + { + return 'getDeploymentDownload'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/:functionId/deployments/:deploymentId/download') + ->httpAlias('/v1/functions/:functionId/deployments/:deploymentId/build/download', ['type' => 'output']) + ->groups(['api', 'functions']) + ->desc('Download deployment') + ->label('scope', 'functions.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'getDeploymentDownload', + description: <<<EOT + 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. + EOT, + auth: [AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::ANY, + type: MethodType::LOCATION + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->param('type', 'source', new WhiteList(['source', 'output']), 'Deployment file to download. Can be: "source", "output".', true) + ->inject('response') + ->inject('request') + ->inject('dbForProject') + ->inject('deviceForFunctions') + ->inject('deviceForBuilds') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $deploymentId, + string $type, + Response $response, + Request $request, + Database $dbForProject, + Device $deviceForFunctions, + Device $deviceForBuilds + ) { + $function = $dbForProject->getDocument('functions', $functionId); + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if ($deployment->getAttribute('resourceId') !== $function->getId()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + switch ($type) { + case 'output': + $path = $deployment->getAttribute('buildPath', ''); + $device = $deviceForBuilds; + break; + case 'source': + $path = $deployment->getAttribute('sourcePath', ''); + $device = $deviceForFunctions; + break; + } + + if (!$device->exists($path)) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + $response + ->setContentType('application/gzip') + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()) + ->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '.tar.gz"'); + + $size = $device->getFileSize($path); + $rangeHeader = $request->getHeader('range'); + + if (!empty($rangeHeader)) { + $start = $request->getRangeStart(); + $end = $request->getRangeEnd(); + $unit = $request->getRangeUnit(); + + if ($end === null) { + $end = min(($start + MAX_OUTPUT_CHUNK_SIZE - 1), ($size - 1)); + } + + if ($unit !== 'bytes' || $start >= $end || $end >= $size) { + throw new Exception(Exception::STORAGE_INVALID_RANGE); + } + + $response + ->addHeader('Accept-Ranges', 'bytes') + ->addHeader('Content-Range', 'bytes ' . $start . '-' . $end . '/' . $size) + ->addHeader('Content-Length', $end - $start + 1) + ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); + + $response->send($device->read($path, $start, ($end - $start + 1))); + } + + if ($size > APP_STORAGE_READ_BUFFER) { + for ($i = 0; $i < ceil($size / MAX_OUTPUT_CHUNK_SIZE); $i++) { + $response->chunk( + $device->read( + $path, + ($i * MAX_OUTPUT_CHUNK_SIZE), + min(MAX_OUTPUT_CHUNK_SIZE, $size - ($i * MAX_OUTPUT_CHUNK_SIZE)) + ), + (($i + 1) * MAX_OUTPUT_CHUNK_SIZE) >= $size + ); + } + } else { + $response->send($device->read($path)); + } + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php new file mode 100644 index 0000000000..eb672dacf9 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php @@ -0,0 +1,136 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Duplicate; + +use Appwrite\Event\Build; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +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\Helpers\ID; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Storage\Device; + +class Create extends Action +{ + use HTTP; + + public static function getName() + { + return 'createDuplicateDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/functions/:functionId/deployments/duplicate') + ->httpAlias('/v1/functions/:functionId/deployments/:deploymentId/build') + ->httpAlias('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId') + ->desc('Create duplicate deployment') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('event', 'functions.[functionId].deployments.[deploymentId].update') + ->label('audits.event', 'deployment.update') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'createDuplicateDeployment', + description: <<<EOT + 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. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_DEPLOYMENT, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->param('buildId', '', new UID(), 'Build unique ID.', true) // added as optional param for backward compatibility + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForBuilds') + ->inject('deviceForFunctions') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $deploymentId, + string $buildId, + Response $response, + Database $dbForProject, + Event $queueForEvents, + Build $queueForBuilds, + Device $deviceForFunctions + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + $path = $deployment->getAttribute('sourcePath'); + if (empty($path) || !$deviceForFunctions->exists($path)) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + $deploymentId = ID::unique(); + + $destination = $deviceForFunctions->getPath($deploymentId . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); + $deviceForFunctions->transfer($path, $destination, $deviceForFunctions); + + $deployment->removeAttribute('$internalId'); + $deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([ + '$internalId' => '', + '$id' => $deploymentId, + 'sourcePath' => $destination, + 'totalSize' => $deployment->getAttribute('sourceSize', 0), + 'entrypoint' => $function->getAttribute('entrypoint'), + 'buildCommands' => $function->getAttribute('commands', ''), + 'search' => implode(' ', [$deploymentId, $function->getAttribute('entrypoint')]), + 'buildStartAt' => null, + 'buildEndAt' => null, + 'buildDuration' => null, + 'buildSize' => null, + 'status' => 'waiting', + 'buildPath' => '', + 'buildLogs' => '', + ])); + + $function = $function + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); + + $queueForBuilds + ->setType(BUILD_TYPE_DEPLOYMENT) + ->setResource($function) + ->setDeployment($deployment); + + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php new file mode 100644 index 0000000000..4efc2bd8b4 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Get.php @@ -0,0 +1,78 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Deployments; + +use Appwrite\Extend\Exception; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Get extends Action +{ + use HTTP; + + public static function getName() + { + return 'getDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/:functionId/deployments/:deploymentId') + ->desc('Get deployment') + ->groups(['api', 'functions']) + ->label('scope', 'functions.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'getDeployment', + description: <<<EOT + Get a function deployment by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DEPLOYMENT, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $deploymentId, + Response $response, + Database $dbForProject + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if ($deployment->getAttribute('resourceId') !== $function->getId()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + $response->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php new file mode 100644 index 0000000000..ea7f67e9da --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php @@ -0,0 +1,119 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Status; + +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Executor\Executor; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Update extends Action +{ + use HTTP; + + public static function getName() + { + return 'updateDeploymentStatus'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/functions/:functionId/deployments/:deploymentId/status') + ->httpAlias('/v1/functions/:functionId/deployments/:deploymentId/build') + ->desc('Update deployment status') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('audits.event', 'deployment.update') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'updateDeploymentStatus', + description: <<<EOT + 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. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DEPLOYMENT, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('project') + ->inject('queueForEvents') + ->inject('executor') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $deploymentId, + Response $response, + Database $dbForProject, + Document $project, + Event $queueForEvents, + Executor $executor + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if (\in_array($deployment->getAttribute('status'), ['ready', 'failed'])) { + throw new Exception(Exception::BUILD_ALREADY_COMPLETED); + } + + $startTime = new \DateTime($deployment->getAttribute('buildStartAt', 'now')); + $endTime = new \DateTime('now'); + $duration = $endTime->getTimestamp() - $startTime->getTimestamp(); + + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttributes([ + 'buildEndAt' => DateTime::now(), + 'buildDuration' => $duration, + 'status' => 'canceled' + ])); + + if ($deployment->getInternalId() === $function->getAttribute('latestDeploymentInternalId', '')) { + $function = $function->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); + } + + try { + $executor->deleteRuntime($project->getId(), $deploymentId . "-build"); + } catch (\Throwable $th) { + // Don't throw if the deployment doesn't exist + if ($th->getCode() !== 404) { + throw $th; + } + } + + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php new file mode 100644 index 0000000000..98a975545d --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -0,0 +1,174 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Template; + +use Appwrite\Event\Build; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Swoole\Request; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; +use Utopia\VCS\Adapter\Git\GitHub; + +class Create extends Base +{ + use HTTP; + + public static function getName() + { + return 'createTemplateDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/functions/:functionId/deployments/template') + ->desc('Create template deployment') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('event', 'functions.[functionId].deployments.[deploymentId].create') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('audits.event', 'deployment.create') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'createTemplateDeployment', + description: <<<EOT + Create a deployment based on a template. + + Use this endpoint with combination of [listTemplates](https://appwrite.io/docs/server/functions#listTemplates) to find the template details. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_DEPLOYMENT, + ) + ], + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('repository', '', new Text(128, 0), 'Repository name of the template.') + ->param('owner', '', new Text(128, 0), 'The name of the owner of the template.') + ->param('rootDirectory', '', new Text(128, 0), 'Path to function code in the template repo.') + ->param('version', '', new Text(128, 0), 'Version (tag) for the repo linked to the function template.') + ->param('activate', false, new Boolean(), 'Automatically activate the deployment when it is finished building.', true) + ->inject('request') + ->inject('response') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->inject('queueForEvents') + ->inject('project') + ->inject('queueForBuilds') + ->inject('gitHub') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $repository, + string $owner, + string $rootDirectory, + string $version, + bool $activate, + Request $request, + Response $response, + Database $dbForProject, + Database $dbForPlatform, + Event $queueForEvents, + Document $project, + Build $queueForBuilds, + GitHub $github + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $template = new Document([ + 'repositoryName' => $repository, + 'ownerName' => $owner, + 'rootDirectory' => $rootDirectory, + 'version' => $version + ]); + + if (!empty($function->getAttribute('providerRepositoryId'))) { + $installation = $dbForPlatform->getDocument('installations', $function->getAttribute('installationId')); + + $deployment = $this->redeployVcsFunction( + request: $request, + function: $function, + project: $project, + installation: $installation, + dbForProject: $dbForProject, + queueForBuilds: $queueForBuilds, + template: $template, + github: $github, + activate: $activate + ); + + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + + return; + } + + $deploymentId = ID::unique(); + $deployment = $dbForProject->createDocument('deployments', new Document([ + '$id' => $deploymentId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'resourceId' => $function->getId(), + 'resourceInternalId' => $function->getInternalId(), + 'resourceType' => 'functions', + 'entrypoint' => $function->getAttribute('entrypoint', ''), + 'buildCommands' => $function->getAttribute('commands', ''), + 'type' => 'manual', + 'search' => implode(' ', [$deploymentId, $function->getAttribute('entrypoint', '')]), + 'activate' => $activate, + ])); + + $function = $function + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('functions', $function->getId(), $function); + + $queueForBuilds + ->setType(BUILD_TYPE_DEPLOYMENT) + ->setResource($function) + ->setDeployment($deployment) + ->setTemplate($template); + + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php new file mode 100644 index 0000000000..1e1b6ac1cc --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Vcs/Create.php @@ -0,0 +1,123 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Vcs; + +use Appwrite\Event\Build; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Swoole\Request; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; +use Utopia\VCS\Adapter\Git\GitHub; + +class Create extends Base +{ + use HTTP; + + public static function getName() + { + return 'createVcsDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/functions/:functionId/deployments/vcs') + ->desc('Create VCS deployment') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('event', 'functions.[functionId].deployments.[deploymentId].create') + ->label('audits.event', 'deployment.create') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'createVcsDeployment', + description: <<<EOT + Create a deployment when a function is connected to VCS. + + This endpoint lets you create deployment from a branch, commit, or a tag. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_DEPLOYMENT, + ) + ], + )) + ->param('functionId', '', new UID(), 'Function ID.') + // TODO: Support tag in future + ->param('type', '', new WhiteList(['branch', 'commit']), 'Type of reference passed. Allowed values are: branch, commit') + ->param('reference', '', new Text(255), 'VCS reference to create deployment from. Depending on type this can be: branch name, commit hash') + ->param('activate', false, new Boolean(), 'Automatically activate the deployment when it is finished building.', true) + ->inject('request') + ->inject('response') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->inject('project') + ->inject('queueForEvents') + ->inject('queueForBuilds') + ->inject('gitHub') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $type, + string $reference, + bool $activate, + Request $request, + Response $response, + Database $dbForProject, + Database $dbForPlatform, + Document $project, + Event $queueForEvents, + Build $queueForBuilds, + GitHub $github + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $template = new Document(); + + $installation = $dbForPlatform->getDocument('installations', $function->getAttribute('installationId')); + + $deployment = $this->redeployVcsFunction( + request: $request, + function: $function, + project: $project, + installation: $installation, + dbForProject: $dbForProject, + queueForBuilds: $queueForBuilds, + template: $template, + github: $github, + activate: $activate, + reference: $reference, + referenceType: $type + ); + + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php new file mode 100644 index 0000000000..85247e63e4 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php @@ -0,0 +1,123 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Deployments; + +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Database\Validator\Queries\Deployments; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Exception\Query as QueryException; +use Utopia\Database\Query; +use Utopia\Database\Validator\Query\Cursor; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Text; + +class XList extends Action +{ + use HTTP; + + public static function getName() + { + return 'listDeployments'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/:functionId/deployments') + ->desc('List deployments') + ->groups(['api', 'functions']) + ->label('scope', 'functions.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listDeployments', + description: <<<EOT + Get a list of all the function's code deployments. You can use the query params to filter your results. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DEPLOYMENT_LIST, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('queries', [], new Deployments(), '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(', ', Deployments::ALLOWED_ATTRIBUTES), true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + array $queries, + string $search, + Response $response, + Database $dbForProject + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + // Set resource queries + $queries[] = Query::equal('resourceInternalId', [$function->getInternalId()]); + $queries[] = Query::equal('resourceType', ['functions']); + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + if ($cursor) { + /** @var Query $cursor */ + + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $deploymentId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('deployments', $deploymentId); + + if ($cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Deployment '{$deploymentId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + + $results = $dbForProject->find('deployments', $queries); + $total = $dbForProject->count('deployments', $filterQueries, APP_LIMIT_COUNT); + + $response->dynamic(new Document([ + 'deployments' => $results, + 'total' => $total, + ]), Response::MODEL_DEPLOYMENT_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php new file mode 100644 index 0000000000..1c7e771430 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -0,0 +1,486 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Executions; + +use Ahc\Jwt\JWT; +use Appwrite\Auth\Auth; +use Appwrite\Event\Event; +use Appwrite\Event\Func; +use Appwrite\Event\StatsUsage; +use Appwrite\Extend\Exception; +use Appwrite\Extend\Exception as AppwriteException; +use Appwrite\Functions\Validator\Headers; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\Platform\Tasks\ScheduleExecutions; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Executor\Executor; +use MaxMind\Db\Reader; +use Utopia\CLI\Console; +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Datetime as DatetimeValidator; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Swoole\Request; +use Utopia\System\System; +use Utopia\Validator\AnyOf; +use Utopia\Validator\Assoc; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; + +class Create extends Base +{ + use HTTP; + + public static function getName() + { + return 'createExecution'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/functions/:functionId/executions') + ->desc('Create execution') + ->groups(['api', 'functions']) + ->label('scope', 'execution.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('event', 'functions.[functionId].executions.[executionId].create') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'createExecution', + description: <<<EOT + 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. + EOT, + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_EXECUTION, + ) + ], + contentType: ContentType::MULTIPART, + requestType: 'application/json', + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('body', '', new Text(10485760, 0), 'HTTP body of execution. Default value is empty string.', true) + ->param('async', false, new Boolean(true), 'Execute code in the background. Default value is false.', true) + ->param('path', '/', new Text(2048), 'HTTP path of execution. Path can include query params. Default value is /', true) + ->param('method', 'POST', new Whitelist(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], true), 'HTTP method of execution. Default value is GET.', true) + ->param('headers', [], new AnyOf([new Assoc(), new Text(65535)], AnyOf::TYPE_MIXED), 'HTTP headers of execution. Defaults to empty.', true) + ->param('scheduledAt', null, new DatetimeValidator(requireDateInFuture: true, precision: DateTimeValidator::PRECISION_MINUTES, offset: 60), '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.', true) + ->inject('response') + ->inject('request') + ->inject('project') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->inject('user') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->inject('queueForFunctions') + ->inject('geodb') + ->inject('executor') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $body, + mixed $async, + string $path, + string $method, + mixed $headers, + ?string $scheduledAt, + Response $response, + Request $request, + Document $project, + Database $dbForProject, + Database $dbForPlatform, + Document $user, + Event $queueForEvents, + StatsUsage $queueForStatsUsage, + Func $queueForFunctions, + Reader $geodb, + Executor $executor + ) { + $async = \strval($async) === 'true' || \strval($async) === '1'; + + if (!$async && !is_null($scheduledAt)) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Scheduled executions must run asynchronously. Set scheduledAt to a future date, or set async to true.'); + } + + /** + * @var array<string, mixed> $headers + */ + $assocParams = ['headers']; + foreach ($assocParams as $assocParam) { + if (!empty('headers') && !is_array($$assocParam)) { + $$assocParam = \json_decode($$assocParam, true); + } + } + + $booleanParams = ['async']; + foreach ($booleanParams as $booleamParam) { + if (!empty($$booleamParam) && !is_bool($$booleamParam)) { + $$booleamParam = $$booleamParam === "true" ? true : false; + } + } + + // 'headers' validator + $validator = new Headers(); + if (!$validator->isValid($headers)) { + throw new Exception($validator->getDescription(), 400); + } + + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $version = $function->getAttribute('version', 'v2'); + $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); + $spec = Config::getParam('specifications')[$function->getAttribute('specification', APP_COMPUTE_SPECIFICATION_DEFAULT)]; + + $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null; + + if (\is_null($runtime)) { + throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); + } + + $deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', ''))); + + if ($deployment->getAttribute('resourceId') !== $function->getId()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); + } + + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function'); + } + + if ($deployment->getAttribute('status') !== 'ready') { + throw new Exception(Exception::BUILD_NOT_READY); + } + + $validator = new Authorization('execute'); + + if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function + throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription()); + } + + $jwt = ''; // initialize + if (!$user->isEmpty()) { // If userId exists, generate a JWT for function + $sessions = $user->getAttribute('sessions', []); + $current = new Document(); + + foreach ($sessions as $session) { + /** @var Utopia\Database\Document $session */ + if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too + $current = $session; + } + } + + if (!$current->isEmpty()) { + $jwtExpiry = $function->getAttribute('timeout', 900); + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $jwtExpiry, 0); + $jwt = $jwtObj->encode([ + 'userId' => $user->getId(), + 'sessionId' => $current->getId(), + ]); + } + } + + $jwtExpiry = $function->getAttribute('timeout', 900); + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $jwtExpiry, 0); + $apiKey = $jwtObj->encode([ + 'projectId' => $project->getId(), + 'scopes' => $function->getAttribute('scopes', []) + ]); + + $headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $apiKey; + $headers['x-appwrite-trigger'] = 'http'; + $headers['x-appwrite-user-id'] = $user->getId() ?? ''; + $headers['x-appwrite-user-jwt'] = $jwt ?? ''; + $headers['x-appwrite-country-code'] = ''; + $headers['x-appwrite-continent-code'] = ''; + $headers['x-appwrite-continent-eu'] = 'false'; + + $ip = $headers['x-real-ip'] ?? ''; + if (!empty($ip)) { + $record = $geodb->get($ip); + + if ($record) { + $eu = Config::getParam('locale-eu'); + + $headers['x-appwrite-country-code'] = $record['country']['iso_code'] ?? ''; + $headers['x-appwrite-continent-code'] = $record['continent']['code'] ?? ''; + $headers['x-appwrite-continent-eu'] = (\in_array($record['country']['iso_code'], $eu)) ? 'true' : 'false'; + } + } + + $headersFiltered = []; + foreach ($headers as $key => $value) { + if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_REQUEST)) { + $headersFiltered[] = ['name' => $key, 'value' => $value]; + } + } + + $executionId = ID::unique(); + + $status = $async ? 'waiting' : 'processing'; + + if (!is_null($scheduledAt)) { + $status = 'scheduled'; + } + + $execution = new Document([ + '$id' => $executionId, + '$permissions' => !$user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], + 'resourceInternalId' => $function->getInternalId(), + 'resourceId' => $function->getId(), + 'resourceType' => 'functions', + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentId' => $deployment->getId(), + 'trigger' => (!is_null($scheduledAt)) ? 'schedule' : 'http', + 'status' => $status, // waiting / processing / completed / failed / scheduled + 'responseStatusCode' => 0, + 'responseHeaders' => [], + 'requestPath' => $path, + 'requestMethod' => $method, + 'requestHeaders' => $headersFiltered, + 'errors' => '', + 'logs' => '', + 'duration' => 0.0, + ]); + + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('executionId', $execution->getId()) + ->setContext('function', $function); + + if ($async) { + if (is_null($scheduledAt)) { + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + $queueForFunctions + ->setType('http') + ->setExecution($execution) + ->setFunction($function) + ->setBody($body) + ->setHeaders($headers) + ->setPath($path) + ->setMethod($method) + ->setJWT($jwt) + ->setProject($project) + ->setUser($user) + ->setParam('functionId', $function->getId()) + ->setParam('executionId', $execution->getId()) + ->trigger(); + } else { + $data = [ + 'headers' => $headers, + 'path' => $path, + 'method' => $method, + 'body' => $body, + 'userId' => $user->getId() + ]; + + $schedule = $dbForPlatform->createDocument('schedules', new Document([ + 'region' => $project->getAttribute('region'), + 'resourceType' => ScheduleExecutions::getSupportedResource(), + 'resourceId' => $execution->getId(), + 'resourceInternalId' => $execution->getInternalId(), + 'resourceUpdatedAt' => DateTime::now(), + 'projectId' => $project->getId(), + 'schedule' => $scheduledAt, + 'data' => $data, + 'active' => true, + ])); + + $execution = $execution + ->setAttribute('scheduleId', $schedule->getId()) + ->setAttribute('scheduleInternalId', $schedule->getInternalId()) + ->setAttribute('scheduledAt', $scheduledAt); + + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + } + + return $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($execution, Response::MODEL_EXECUTION); + } + + $durationStart = \microtime(true); + + $vars = []; + + // V2 vars + if ($version === 'v2') { + $vars = \array_merge($vars, [ + 'APPWRITE_FUNCTION_TRIGGER' => $headers['x-appwrite-trigger'] ?? '', + 'APPWRITE_FUNCTION_DATA' => $body ?? '', + 'APPWRITE_FUNCTION_USER_ID' => $headers['x-appwrite-user-id'] ?? '', + 'APPWRITE_FUNCTION_JWT' => $headers['x-appwrite-user-jwt'] ?? '' + ]); + } + + // Shared vars + foreach ($function->getAttribute('varsProject', []) as $var) { + $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); + } + + // Function vars + foreach ($function->getAttribute('vars', []) as $var) { + $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); + } + + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $hostname = System::getEnv('_APP_DOMAIN'); + $endpoint = $protocol . '://' . $hostname . "/v1"; + + // Appwrite vars + $vars = \array_merge($vars, [ + 'APPWRITE_FUNCTION_API_ENDPOINT' => $endpoint, + 'APPWRITE_FUNCTION_ID' => $functionId, + 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name'), + 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), + 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), + 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', + 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', + 'APPWRITE_FUNCTION_CPUS' => $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT, + 'APPWRITE_FUNCTION_MEMORY' => $spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT, + 'APPWRITE_VERSION' => APP_VERSION_STABLE, + 'APPWRITE_REGION' => $project->getAttribute('region'), + 'APPWRITE_DEPLOYMENT_TYPE' => $deployment->getAttribute('type', ''), + 'APPWRITE_VCS_REPOSITORY_ID' => $deployment->getAttribute('providerRepositoryId', ''), + 'APPWRITE_VCS_REPOSITORY_NAME' => $deployment->getAttribute('providerRepositoryName', ''), + 'APPWRITE_VCS_REPOSITORY_OWNER' => $deployment->getAttribute('providerRepositoryOwner', ''), + 'APPWRITE_VCS_REPOSITORY_URL' => $deployment->getAttribute('providerRepositoryUrl', ''), + 'APPWRITE_VCS_REPOSITORY_BRANCH' => $deployment->getAttribute('providerBranch', ''), + 'APPWRITE_VCS_REPOSITORY_BRANCH_URL' => $deployment->getAttribute('providerBranchUrl', ''), + 'APPWRITE_VCS_COMMIT_HASH' => $deployment->getAttribute('providerCommitHash', ''), + 'APPWRITE_VCS_COMMIT_MESSAGE' => $deployment->getAttribute('providerCommitMessage', ''), + 'APPWRITE_VCS_COMMIT_URL' => $deployment->getAttribute('providerCommitUrl', ''), + 'APPWRITE_VCS_COMMIT_AUTHOR_NAME' => $deployment->getAttribute('providerCommitAuthor', ''), + 'APPWRITE_VCS_COMMIT_AUTHOR_URL' => $deployment->getAttribute('providerCommitAuthorUrl', ''), + 'APPWRITE_VCS_ROOT_DIRECTORY' => $deployment->getAttribute('providerRootDirectory', ''), + ]); + + /** Execute function */ + try { + $version = $function->getAttribute('version', 'v2'); + $command = $runtime['startCommand']; + $command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"'; + $executionResponse = $executor->createExecution( + projectId: $project->getId(), + deploymentId: $deployment->getId(), + body: \strlen($body) > 0 ? $body : null, + variables: $vars, + timeout: $function->getAttribute('timeout', 0), + image: $runtime['image'], + source: $deployment->getAttribute('buildPath', ''), + entrypoint: $deployment->getAttribute('entrypoint', ''), + version: $version, + path: $path, + method: $method, + headers: $headers, + runtimeEntrypoint: $command, + cpus: $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT, + memory: $spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT, + logging: $function->getAttribute('logging', true), + requestTimeout: 30 + ); + + $headersFiltered = []; + foreach ($executionResponse['headers'] as $key => $value) { + if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_RESPONSE)) { + $headersFiltered[] = ['name' => $key, 'value' => $value]; + } + } + + /** Update execution status */ + $status = $executionResponse['statusCode'] >= 500 ? 'failed' : 'completed'; + $execution->setAttribute('status', $status); + $execution->setAttribute('responseStatusCode', $executionResponse['statusCode']); + $execution->setAttribute('responseHeaders', $headersFiltered); + $execution->setAttribute('logs', $executionResponse['logs']); + $execution->setAttribute('errors', $executionResponse['errors']); + $execution->setAttribute('duration', $executionResponse['duration']); + } catch (\Throwable $th) { + $durationEnd = \microtime(true); + + $execution + ->setAttribute('duration', $durationEnd - $durationStart) + ->setAttribute('status', 'failed') + ->setAttribute('responseStatusCode', 500) + ->setAttribute('errors', $th->getMessage() . '\nError Code: ' . $th->getCode()); + Console::error($th->getMessage()); + + if ($th instanceof AppwriteException) { + throw $th; + } + } finally { + $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(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(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))) + ; + + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); + } + + $roles = Authorization::getRoles(); + $isPrivilegedUser = Auth::isPrivilegedUser($roles); + $isAppUser = Auth::isAppUser($roles); + + if (!$isPrivilegedUser && !$isAppUser) { + $execution->setAttribute('logs', ''); + $execution->setAttribute('errors', ''); + } + + $headers = []; + foreach (($executionResponse['headers'] ?? []) as $key => $value) { + $headers[] = ['name' => $key, 'value' => $value]; + } + + $execution->setAttribute('responseBody', $executionResponse['body'] ?? ''); + $execution->setAttribute('responseHeaders', $headers); + + $acceptTypes = \explode(', ', $request->getHeader('accept')); + foreach ($acceptTypes as $acceptType) { + if (\str_starts_with($acceptType, 'application/json') || \str_starts_with($acceptType, 'application/*')) { + $response->setContentType(Response::CONTENT_TYPE_JSON); + break; + } elseif (\str_starts_with($acceptType, 'multipart/form-data') || \str_starts_with($acceptType, 'multipart/*')) { + $response->setContentType(Response::CONTENT_TYPE_MULTIPART); + break; + } + } + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($execution, Response::MODEL_EXECUTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php new file mode 100644 index 0000000000..b22adb0565 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -0,0 +1,122 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Executions; + +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\Platform\Tasks\ScheduleExecutions; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Delete extends Base +{ + use HTTP; + + public static function getName() + { + return 'deleteExecution'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/functions/:functionId/executions/:executionId') + ->desc('Delete execution') + ->groups(['api', 'functions']) + ->label('scope', 'execution.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('event', 'functions.[functionId].executions.[executionId].delete') + ->label('audits.event', 'executions.delete') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'deleteExecution', + description: <<<EOT + Delete a function execution by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('executionId', '', new UID(), 'Execution ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $executionId, + Response $response, + Database $dbForProject, + Database $dbForPlatform, + Event $queueForEvents + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $execution = $dbForProject->getDocument('executions', $executionId); + if ($execution->isEmpty()) { + throw new Exception(Exception::EXECUTION_NOT_FOUND); + } + + if ($execution->getAttribute('resourceType') !== 'functions' && $execution->getAttribute('resourceInternalId') !== $function->getInternalId()) { + throw new Exception(Exception::EXECUTION_NOT_FOUND); + } + $status = $execution->getAttribute('status'); + + if (!in_array($status, ['completed', 'failed', 'scheduled'])) { + throw new Exception(Exception::EXECUTION_IN_PROGRESS); + } + + if (!$dbForProject->deleteDocument('executions', $execution->getId())) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove execution from DB'); + } + + if ($status === 'scheduled') { + $schedule = $dbForPlatform->findOne('schedules', [ + Query::equal('resourceId', [$execution->getId()]), + Query::equal('resourceType', [ScheduleExecutions::getSupportedResource()]), + Query::equal('active', [true]), + ]); + + if (!$schedule->isEmpty()) { + $schedule + ->setAttribute('resourceUpdatedAt', DateTime::now()) + ->setAttribute('active', false); + + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + } + } + + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('executionId', $execution->getId()) + ->setPayload($response->output($execution, Response::MODEL_EXECUTION)); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php new file mode 100644 index 0000000000..6a92794767 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -0,0 +1,92 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Executions; + +use Appwrite\Auth\Auth; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\Authorization; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Get extends Base +{ + use HTTP; + + public static function getName() + { + return 'getExecution'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/:functionId/executions/:executionId') + ->desc('Get execution') + ->groups(['api', 'functions']) + ->label('scope', 'execution.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'getExecution', + description: <<<EOT + Get a function execution log by its unique ID. + EOT, + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EXECUTION, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('executionId', '', new UID(), 'Execution ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $executionId, + Response $response, + Database $dbForProject + ) { + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $execution = $dbForProject->getDocument('executions', $executionId); + + if ($execution->getAttribute('resourceType') !== 'functions' || $execution->getAttribute('resourceInternalId') !== $function->getInternalId()) { + throw new Exception(Exception::EXECUTION_NOT_FOUND); + } + + if ($execution->isEmpty()) { + throw new Exception(Exception::EXECUTION_NOT_FOUND); + } + + $roles = Authorization::getRoles(); + $isPrivilegedUser = Auth::isPrivilegedUser($roles); + $isAppUser = Auth::isAppUser($roles); + if (!$isPrivilegedUser && !$isAppUser) { + $execution->setAttribute('logs', ''); + $execution->setAttribute('errors', ''); + } + + $response->dynamic($execution, Response::MODEL_EXECUTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php new file mode 100644 index 0000000000..be1e16225c --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -0,0 +1,133 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Executions; + +use Appwrite\Auth\Auth; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Database\Validator\Queries\Executions; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Exception\Query as QueryException; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Query\Cursor; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listExecutions'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/:functionId/executions') + ->desc('List executions') + ->groups(['api', 'functions']) + ->label('scope', 'execution.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listExecutions', + description: <<<EOT + Get a list of all the current user function execution logs. You can use the query params to filter your results. + EOT, + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EXECUTION_LIST, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('queries', [], new Executions(), '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(', ', Executions::ALLOWED_ATTRIBUTES), true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + array $queries, + Response $response, + Database $dbForProject + ) { + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + if ($function->isEmpty() || (!$function->getAttribute('enabled') && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + // Set internal queries + $queries[] = Query::equal('resourceInternalId', [$function->getInternalId()]); + $queries[] = Query::equal('resourceType', ['functions']); + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + if ($cursor) { + /** @var Query $cursor */ + + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $executionId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('executions', $executionId); + + if ($cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Execution '{$executionId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + + $results = $dbForProject->find('executions', $queries); + $total = $dbForProject->count('executions', $filterQueries, APP_LIMIT_COUNT); + + $roles = Authorization::getRoles(); + $isPrivilegedUser = Auth::isPrivilegedUser($roles); + $isAppUser = Auth::isAppUser($roles); + if (!$isPrivilegedUser && !$isAppUser) { + $results = array_map(function ($execution) { + $execution->setAttribute('logs', ''); + $execution->setAttribute('errors', ''); + return $execution; + }, $results); + } + + $response->dynamic(new Document([ + 'executions' => $results, + 'total' => $total, + ]), Response::MODEL_EXECUTION_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php new file mode 100644 index 0000000000..9436833dad --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -0,0 +1,260 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Functions; + +use Appwrite\Event\Event; +use Appwrite\Event\Validator\FunctionEvent; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\Platform\Modules\Compute\Validator\Specification; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Task\Validator\Cron; +use Appwrite\Utopia\Database\Validator\CustomId; +use Appwrite\Utopia\Response; +use Utopia\Abuse\Abuse; +use Utopia\App; +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Roles; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\System\System; +use Utopia\Validator\ArrayList; +use Utopia\Validator\Boolean; +use Utopia\Validator\Range; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; + +class Create extends Base +{ + use HTTP; + + public static function getName() + { + return 'createFunction'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/functions') + ->desc('Create function') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('event', 'functions.[functionId].create') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('audits.event', 'function.create') + ->label('audits.resource', 'function/{response.$id}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'create', + description: <<<EOT + 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. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_FUNCTION, + ) + ], + )) + ->param('functionId', '', new CustomId(), '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.') + ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') + ->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.') + ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), '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 ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) + ->param('events', [], new ArrayList(new FunctionEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true) + ->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true) + ->param('timeout', 15, new Range(1, (int) System::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Function maximum execution time in seconds.', true) + ->param('enabled', true, new Boolean(), '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.', true) + ->param('logging', true, new Boolean(), 'When disabled, executions will exclude logs and errors, and will be slightly faster.', true) + ->param('entrypoint', '', new Text(1028, 0), 'Entrypoint File. This path is relative to the "providerRootDirectory".', true) + ->param('commands', '', new Text(8192, 0), 'Build Commands.', true) + ->param('scopes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of scopes allowed for API key auto-generated for every execution. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.', true) + ->param('installationId', '', new Text(128, 0), 'Appwrite Installation ID for VCS (Version Control System) deployment.', true) + ->param('providerRepositoryId', '', new Text(128, 0), 'Repository ID of the repo linked to the function.', true) + ->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the function.', true) + ->param('providerSilentMode', false, new Boolean(), '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.', true) + ->param('providerRootDirectory', '', new Text(128, 0), 'Path to function code in the linked repo.', true) + ->param('specification', APP_COMPUTE_SPECIFICATION_DEFAULT, fn (array $plan) => new Specification( + $plan, + Config::getParam('specifications', []), + App::getEnv('_APP_COMPUTE_CPUS', APP_COMPUTE_CPUS_DEFAULT), + App::getEnv('_APP_COMPUTE_MEMORY', APP_COMPUTE_MEMORY_DEFAULT) + ), 'Runtime specification for the function and builds.', true, ['plan']) + ->inject('response') + ->inject('dbForProject') + ->inject('timelimit') + ->inject('project') + ->inject('queueForEvents') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $name, + string $runtime, + array $execute, + array $events, + string $schedule, + int $timeout, + bool $enabled, + bool $logging, + string $entrypoint, + string $commands, + array $scopes, + string $installationId, + string $providerRepositoryId, + string $providerBranch, + bool $providerSilentMode, + string $providerRootDirectory, + string $specification, + Response $response, + Database $dbForProject, + callable $timelimit, + Document $project, + Event $queueForEvents, + Database $dbForPlatform + ) { + + // Temporary abuse check + $abuseCheck = function () use ($project, $timelimit, $response) { + $abuseKey = "projectId:{projectId},url:{url}"; + $abuseLimit = App::getEnv('_APP_FUNCTIONS_CREATION_ABUSE_LIMIT', 50); + $abuseTime = 86400; // 1 day + + $timeLimit = $timelimit($abuseKey, $abuseLimit, $abuseTime); + $timeLimit + ->setParam('{projectId}', $project->getId()) + ->setParam('{url}', '/v1/functions'); + + $abuse = new Abuse($timeLimit); + $remaining = $timeLimit->remaining(); + $limit = $timeLimit->limit(); + $time = $timeLimit->time() + $abuseTime; + + $response + ->addHeader('X-RateLimit-Limit', $limit) + ->addHeader('X-RateLimit-Remaining', $remaining) + ->addHeader('X-RateLimit-Reset', $time); + + $enabled = System::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled'; + if ($enabled && $abuse->check()) { + throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED); + } + }; + + $abuseCheck(); + + $functionId = ($functionId == 'unique()') ? ID::unique() : $functionId; + + $allowList = \array_filter(\explode(',', System::getEnv('_APP_FUNCTIONS_RUNTIMES', ''))); + + if (!empty($allowList) && !\in_array($runtime, $allowList)) { + throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $runtime . '" is not supported'); + } + + $installation = $dbForPlatform->getDocument('installations', $installationId); + + if (!empty($installationId) && $installation->isEmpty()) { + throw new Exception(Exception::INSTALLATION_NOT_FOUND); + } + + if (!empty($providerRepositoryId) && (empty($installationId) || empty($providerBranch))) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'When connecting to VCS (Version Control System), you need to provide "installationId" and "providerBranch".'); + } + + $function = $dbForProject->createDocument('functions', new Document([ + '$id' => $functionId, + 'execute' => $execute, + 'enabled' => $enabled, + 'live' => true, + 'logging' => $logging, + 'name' => $name, + 'runtime' => $runtime, + 'deploymentInternalId' => '', + 'deploymentId' => '', + 'events' => $events, + 'schedule' => $schedule, + 'scheduleInternalId' => '', + 'scheduleId' => '', + 'timeout' => $timeout, + 'entrypoint' => $entrypoint, + 'commands' => $commands, + 'scopes' => $scopes, + 'search' => implode(' ', [$functionId, $name, $runtime]), + 'version' => 'v5', + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getInternalId(), + 'providerRepositoryId' => $providerRepositoryId, + 'repositoryId' => '', + 'repositoryInternalId' => '', + 'providerBranch' => $providerBranch, + 'providerRootDirectory' => $providerRootDirectory, + 'providerSilentMode' => $providerSilentMode, + 'specification' => $specification + ])); + + $schedule = Authorization::skip( + fn () => $dbForPlatform->createDocument('schedules', new Document([ + 'region' => $project->getAttribute('region'), + 'resourceType' => 'function', + 'resourceId' => $function->getId(), + 'resourceInternalId' => $function->getInternalId(), + 'resourceUpdatedAt' => DateTime::now(), + 'projectId' => $project->getId(), + 'schedule' => $function->getAttribute('schedule'), + 'active' => false, + ])) + ); + + $function->setAttribute('scheduleId', $schedule->getId()); + $function->setAttribute('scheduleInternalId', $schedule->getInternalId()); + + // Git connect logic + if (!empty($providerRepositoryId)) { + $teamId = $project->getAttribute('teamId', ''); + + $repository = $dbForPlatform->createDocument('repositories', new Document([ + '$id' => ID::unique(), + '$permissions' => [ + Permission::read(Role::team(ID::custom($teamId))), + Permission::update(Role::team(ID::custom($teamId), 'owner')), + Permission::update(Role::team(ID::custom($teamId), 'developer')), + Permission::delete(Role::team(ID::custom($teamId), 'owner')), + Permission::delete(Role::team(ID::custom($teamId), 'developer')), + ], + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getInternalId(), + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'providerRepositoryId' => $providerRepositoryId, + 'resourceId' => $function->getId(), + 'resourceInternalId' => $function->getInternalId(), + 'resourceType' => 'function', + 'providerPullRequestIds' => [] + ])); + + $function->setAttribute('repositoryId', $repository->getId()); + $function->setAttribute('repositoryInternalId', $repository->getInternalId()); + } + + $function = $dbForProject->updateDocument('functions', $function->getId(), $function); + + $queueForEvents->setParam('functionId', $function->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($function, Response::MODEL_FUNCTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php new file mode 100644 index 0000000000..40112756ea --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php @@ -0,0 +1,99 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Functions; + +use Appwrite\Event\Delete as DeleteEvent; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Delete extends Base +{ + use HTTP; + + public static function getName() + { + return 'deleteFunction'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/functions/:functionId') + ->desc('Delete function') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('event', 'functions.[functionId].delete') + ->label('audits.event', 'function.delete') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'delete', + description: <<<EOT + Delete a function by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDeletes') + ->inject('queueForEvents') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + Response $response, + Database $dbForProject, + DeleteEvent $queueForDeletes, + Event $queueForEvents, + Database $dbForPlatform + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + if (!$dbForProject->deleteDocument('functions', $function->getId())) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove function from DB'); + } + + // Inform scheduler to no longer run function + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule + ->setAttribute('resourceUpdatedAt', DateTime::now()) + ->setAttribute('active', false); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + + $queueForDeletes + ->setType(DELETE_TYPE_DOCUMENT) + ->setDocument($function); + + $queueForEvents->setParam('functionId', $function->getId()); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php new file mode 100644 index 0000000000..c957a688e2 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -0,0 +1,133 @@ +<?php + +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; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Update extends Base +{ + use HTTP; + + public static function getName() + { + return 'updateFunctionDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/functions/:functionId/deployment') + ->httpAlias('/v1/functions/:functionId/deployments/:deploymentId') + ->desc('Update function\'s deployment') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('event', 'functions.[functionId].deployments.[deploymentId].update') + ->label('audits.event', 'deployment.update') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'updateFunctionDeployment', + description: <<<EOT + Update the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FUNCTION, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->inject('project') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $deploymentId, + Document $project, + Response $response, + Database $dbForProject, + Event $queueForEvents, + Database $dbForPlatform + ) { + $function = $dbForProject->getDocument('functions', $functionId); + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if ($deployment->getAttribute('status') !== 'ready') { + 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(), + 'deploymentCreatedAt' => $deployment->getCreatedAt(), + ]))); + + // Inform scheduler if function is still active + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule + ->setAttribute('resourceUpdatedAt', DateTime::now()) + ->setAttribute('schedule', $function->getAttribute('schedule')) + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + + $queries = [ + Query::equal('trigger', 'manual'), + Query::equal("type", ["deployment"]), + Query::equal("deploymentResourceType", ["function"]), + Query::equal("deploymentResourceInternalId", [$function->getInternalId()]), + ]; + + 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()) + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); + }); + + $queueForEvents + ->setParam('functionId', $function->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response->dynamic($function, Response::MODEL_FUNCTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Get.php new file mode 100644 index 0000000000..fb58e9b2d1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Get.php @@ -0,0 +1,67 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Functions; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Get extends Base +{ + use HTTP; + + public static function getName() + { + return 'getFunction'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/:functionId') + ->desc('Get function') + ->groups(['api', 'functions']) + ->label('scope', 'functions.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'get', + description: <<<EOT + Get a function by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FUNCTION, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + Response $response, + Database $dbForProject + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $response->dynamic($function, Response::MODEL_FUNCTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php new file mode 100644 index 0000000000..3e4399f8db --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -0,0 +1,291 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Functions; + +use Appwrite\Event\Build; +use Appwrite\Event\Event; +use Appwrite\Event\Validator\FunctionEvent; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\Platform\Modules\Compute\Validator\Specification; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Task\Validator\Cron; +use Appwrite\Utopia\Response; +use Executor\Executor; +use Utopia\App; +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\Roles; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Swoole\Request; +use Utopia\System\System; +use Utopia\Validator\ArrayList; +use Utopia\Validator\Boolean; +use Utopia\Validator\Nullable; +use Utopia\Validator\Range; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; +use Utopia\VCS\Adapter\Git\GitHub; + +class Update extends Base +{ + use HTTP; + + public static function getName() + { + return 'updateFunction'; + } + + public function __construct() + { + $this->setHttpMethod(Action::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/functions/:functionId') + ->desc('Update function') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('event', 'functions.[functionId].update') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('audits.event', 'function.update') + ->label('audits.resource', 'function/{response.$id}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'update', + description: <<<EOT + Update function by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FUNCTION, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('name', '', new Text(128), 'Function name. Max length: 128 chars.') + ->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.', true) + ->param('execute', [], new Roles(APP_LIMIT_ARRAY_PARAMS_SIZE), '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 ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 64 characters long.', true) + ->param('events', [], new ArrayList(new FunctionEvent(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.', true) + ->param('schedule', '', new Cron(), 'Schedule CRON syntax.', true) + ->param('timeout', 15, new Range(1, (int) System::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Maximum execution time in seconds.', true) + ->param('enabled', true, new Boolean(), '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.', true) + ->param('logging', true, new Boolean(), 'When disabled, executions will exclude logs and errors, and will be slightly faster.', true) + ->param('entrypoint', '', new Text(1028, 0), 'Entrypoint File. This path is relative to the "providerRootDirectory".', true) + ->param('commands', '', new Text(8192, 0), 'Build Commands.', true) + ->param('scopes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('scopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of scopes allowed for API Key auto-generated for every execution. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.', true) + ->param('installationId', '', new Text(128, 0), 'Appwrite Installation ID for VCS (Version Controle System) deployment.', true) + ->param('providerRepositoryId', null, new Nullable(new Text(128, 0)), 'Repository ID of the repo linked to the function', true) + ->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the function', true) + ->param('providerSilentMode', false, new Boolean(), '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.', true) + ->param('providerRootDirectory', '', new Text(128, 0), 'Path to function code in the linked repo.', true) + ->param('specification', APP_COMPUTE_SPECIFICATION_DEFAULT, fn (array $plan) => new Specification( + $plan, + Config::getParam('specifications', []), + App::getEnv('_APP_COMPUTE_CPUS', APP_COMPUTE_CPUS_DEFAULT), + App::getEnv('_APP_COMPUTE_MEMORY', APP_COMPUTE_MEMORY_DEFAULT) + ), 'Runtime specification for the function and builds.', true, ['plan']) + ->inject('request') + ->inject('response') + ->inject('dbForProject') + ->inject('project') + ->inject('queueForEvents') + ->inject('queueForBuilds') + ->inject('dbForPlatform') + ->inject('gitHub') + ->inject('executor') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $name, + string $runtime, + array $execute, + array $events, + string $schedule, + int $timeout, + bool $enabled, + bool $logging, + string $entrypoint, + string $commands, + array $scopes, + string $installationId, + ?string $providerRepositoryId, + string $providerBranch, + bool $providerSilentMode, + string $providerRootDirectory, + string $specification, + Request $request, + Response $response, + Database $dbForProject, + Document $project, + Event $queueForEvents, + Build $queueForBuilds, + Database $dbForPlatform, + GitHub $github, + Executor $executor + ) { + // TODO: If only branch changes, re-deploy + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $installation = $dbForPlatform->getDocument('installations', $installationId); + + if (!empty($installationId) && $installation->isEmpty()) { + throw new Exception(Exception::INSTALLATION_NOT_FOUND); + } + + if (!empty($providerRepositoryId) && (empty($installationId) || empty($providerBranch))) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'When connecting to VCS (Version Control System), you need to provide "installationId" and "providerBranch".'); + } + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + if (empty($runtime)) { + $runtime = $function->getAttribute('runtime'); + } + + $enabled ??= $function->getAttribute('enabled', true); + + $repositoryId = $function->getAttribute('repositoryId', ''); + $repositoryInternalId = $function->getAttribute('repositoryInternalId', ''); + + if (empty($entrypoint)) { + $entrypoint = $function->getAttribute('entrypoint', ''); + } + + $isConnected = !empty($function->getAttribute('providerRepositoryId', '')); + + // 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('resourceType', ['function']), + Query::limit(100), + ]); + + foreach ($repositories as $repository) { + $dbForPlatform->deleteDocument('repositories', $repository->getId()); + } + + $providerRepositoryId = ''; + $installationId = ''; + $providerBranch = ''; + $providerRootDirectory = ''; + $providerSilentMode = true; + $repositoryId = ''; + $repositoryInternalId = ''; + } + + // Git connect logic + if (!$isConnected && !empty($providerRepositoryId)) { + $teamId = $project->getAttribute('teamId', ''); + + $repository = $dbForPlatform->createDocument('repositories', new Document([ + '$id' => ID::unique(), + '$permissions' => [ + Permission::read(Role::team(ID::custom($teamId))), + Permission::update(Role::team(ID::custom($teamId), 'owner')), + Permission::update(Role::team(ID::custom($teamId), 'developer')), + Permission::delete(Role::team(ID::custom($teamId), 'owner')), + Permission::delete(Role::team(ID::custom($teamId), 'developer')), + ], + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getInternalId(), + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'providerRepositoryId' => $providerRepositoryId, + 'resourceId' => $function->getId(), + 'resourceInternalId' => $function->getInternalId(), + 'resourceType' => 'function', + 'providerPullRequestIds' => [] + ])); + + $repositoryId = $repository->getId(); + $repositoryInternalId = $repository->getInternalId(); + } + + $live = true; + + if ( + $function->getAttribute('name') !== $name || + $function->getAttribute('entrypoint') !== $entrypoint || + $function->getAttribute('commands') !== $commands || + $function->getAttribute('providerRootDirectory') !== $providerRootDirectory || + $function->getAttribute('runtime') !== $runtime + ) { + $live = false; + } + + // Enforce Cold Start if spec limits change. + if ($function->getAttribute('specification') !== $specification && !empty($function->getAttribute('deploymentId'))) { + try { + $executor->deleteRuntime($project->getId(), $function->getAttribute('deploymentId')); + } catch (\Throwable $th) { + // Don't throw if the deployment doesn't exist + if ($th->getCode() !== 404) { + throw $th; + } + } + } + + $function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [ + 'execute' => $execute, + 'name' => $name, + 'runtime' => $runtime, + 'events' => $events, + 'schedule' => $schedule, + 'timeout' => $timeout, + 'enabled' => $enabled, + 'live' => $live, + 'logging' => $logging, + 'entrypoint' => $entrypoint, + 'commands' => $commands, + 'scopes' => $scopes, + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getInternalId(), + 'providerRepositoryId' => $providerRepositoryId, + 'repositoryId' => $repositoryId, + 'repositoryInternalId' => $repositoryInternalId, + 'providerBranch' => $providerBranch, + 'providerRootDirectory' => $providerRootDirectory, + 'providerSilentMode' => $providerSilentMode, + 'specification' => $specification, + 'search' => implode(' ', [$functionId, $name, $runtime]), + ]))); + + // Redeploy logic + if (!$isConnected && !empty($providerRepositoryId)) { + $this->redeployVcsFunction($request, $function, $project, $installation, $dbForProject, $queueForBuilds, new Document(), $github, true); + } + + // Inform scheduler if function is still active + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule + ->setAttribute('resourceUpdatedAt', DateTime::now()) + ->setAttribute('schedule', $function->getAttribute('schedule')) + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + + $queueForEvents->setParam('functionId', $function->getId()); + + $response->dynamic($function, Response::MODEL_FUNCTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php new file mode 100644 index 0000000000..6bcbb6cfbe --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php @@ -0,0 +1,108 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Functions; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Database\Validator\Queries\Functions; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Exception\Query as QueryException; +use Utopia\Database\Query; +use Utopia\Database\Validator\Query\Cursor; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Text; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listFunctions'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions') + ->groups(['api', 'functions']) + ->desc('List functions') + ->label('scope', 'functions.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'list', + description: <<<EOT + Get a list of all the project's functions. You can use the query params to filter your results. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FUNCTION_LIST, + ) + ] + )) + ->param('queries', [], new Functions(), '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(', ', Functions::ALLOWED_ATTRIBUTES), true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action( + array $queries, + string $search, + Response $response, + Database $dbForProject + ) { + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + if ($cursor) { + /** @var Query $cursor */ + + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $functionId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('functions', $functionId); + + if ($cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Function '{$functionId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + + $response->dynamic(new Document([ + 'functions' => $dbForProject->find('functions', $queries), + 'total' => $dbForProject->count('functions', $filterQueries, APP_LIMIT_COUNT), + ]), Response::MODEL_FUNCTION_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Runtimes/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Runtimes/XList.php new file mode 100644 index 0000000000..f00c4a0cd5 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Runtimes/XList.php @@ -0,0 +1,73 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Runtimes; + +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +use Utopia\Database\Document; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\System\System; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listRuntimes'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/runtimes') + ->groups(['api']) + ->desc('List runtimes') + ->label('scope', 'public') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listRuntimes', + description: <<<EOT + Get a list of all runtimes that are currently active on your instance. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_RUNTIME_LIST, + ) + ] + )) + ->inject('response') + ->callback([$this, 'action']); + } + + public function action(Response $response) + { + $runtimes = Config::getParam('runtimes'); + + $allowList = \array_filter(\explode(',', System::getEnv('_APP_FUNCTIONS_RUNTIMES', ''))); + + $allowed = []; + foreach ($runtimes as $id => $runtime) { + if (!empty($allowList) && !\in_array($id, $allowList)) { + continue; + } + + $runtime['$id'] = $id; + $allowed[] = $runtime; + } + + $response->dynamic(new Document([ + 'total' => count($allowed), + 'runtimes' => $allowed + ]), Response::MODEL_RUNTIME_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Specifications/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Specifications/XList.php new file mode 100644 index 0000000000..375c99966d --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Specifications/XList.php @@ -0,0 +1,76 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Specifications; + +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +use Utopia\Database\Document; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\System\System; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listSpecifications'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/specifications') + ->groups(['api', 'functions']) + ->desc('List specifications') + ->label('scope', 'functions.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listSpecifications', + description: <<<EOT + List allowed function specifications for this instance. + EOT, + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SPECIFICATION_LIST, + ) + ] + )) + ->inject('response') + ->inject('plan') + ->callback([$this, 'action']); + } + + public function action(Response $response, array $plan) + { + $allSpecs = Config::getParam('specifications', []); + + $specs = []; + foreach ($allSpecs as $spec) { + $spec['enabled'] = true; + + if (array_key_exists('specifications', $plan)) { + $spec['enabled'] = in_array($spec['slug'], $plan['specifications']); + } + + // Only add specs that are within the limits set by environment variables + if ($spec['cpus'] <= System::getEnv('_APP_COMPUTE_CPUS', 1) && $spec['memory'] <= System::getEnv('_APP_COMPUTE_MEMORY', 512)) { + $specs[] = $spec; + } + } + + $response->dynamic(new Document([ + 'specifications' => $specs, + 'total' => count($specs) + ]), Response::MODEL_SPECIFICATION_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Templates/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Templates/Get.php new file mode 100644 index 0000000000..8eb95b2026 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Templates/Get.php @@ -0,0 +1,70 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Templates; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +use Utopia\Database\Document; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Text; + +class Get extends Base +{ + use HTTP; + + public static function getName() + { + return 'getTemplate'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/templates/:templateId') + ->desc('Get function template') + ->groups(['api', 'functions']) + ->label('scope', 'public') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'getTemplate', + description: <<<EOT + Get a function template using ID. You can use template details in [createFunction](/docs/references/cloud/server-nodejs/functions#create) method. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEMPLATE_FUNCTION, + ) + ] + )) + ->param('templateId', '', new Text(128), 'Template ID.') + ->inject('response') + ->callback([$this, 'action']); + } + + public function action(string $templateId, Response $response) + { + $templates = Config::getParam('templates-function', []); + + $filtered = \array_filter($templates, function ($template) use ($templateId) { + return $template['id'] === $templateId; + }); + + $template = array_shift($filtered); + + if (empty($template)) { + throw new Exception(Exception::FUNCTION_TEMPLATE_NOT_FOUND); + } + + $response->dynamic(new Document($template), Response::MODEL_TEMPLATE_FUNCTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php new file mode 100644 index 0000000000..7a165e6348 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php @@ -0,0 +1,85 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Templates; + +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +use Utopia\Database\Document; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\ArrayList; +use Utopia\Validator\Range; +use Utopia\Validator\WhiteList; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listTemplates'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/templates') + ->desc('List templates') + ->groups(['api']) + ->label('scope', 'public') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listTemplates', + description: <<<EOT + List available function templates. You can use template details in [createFunction](/docs/references/cloud/server-nodejs/functions#create) method. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEMPLATE_FUNCTION_LIST, + ) + ] + )) + ->param('runtimes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('runtimes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of runtimes allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' runtimes are allowed.', true) + ->param('useCases', [], new ArrayList(new WhiteList(['dev-tools','starter','databases','ai','messaging','utilities']), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering function templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) + ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) + ->param('offset', 0, new Range(0, 5000), 'Offset the list of returned templates. Maximum offset is 5000.', true) + ->inject('response') + ->callback([$this, 'action']); + } + + public function action(array $runtimes, array $usecases, int $limit, int $offset, Response $response) + { + $templates = Config::getParam('templates-function', []); + + if (!empty($runtimes)) { + $templates = \array_filter($templates, function ($template) use ($runtimes) { + return \count(\array_intersect($runtimes, \array_column($template['runtimes'], 'name'))) > 0; + }); + } + + if (!empty($usecases)) { + $templates = \array_filter($templates, function ($template) use ($usecases) { + return \count(\array_intersect($usecases, $template['useCases'])) > 0; + }); + } + + \usort($templates, function ($a, $b) { + return $b['score'] <=> $a['score']; + }); + + $total = \count($templates); + $templates = \array_slice($templates, $offset, $limit); + $response->dynamic(new Document([ + 'templates' => $templates, + 'total' => $total, + ]), Response::MODEL_TEMPLATE_FUNCTION_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php new file mode 100644 index 0000000000..7f64fa8d8c --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -0,0 +1,158 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Usage; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +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; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\WhiteList; + +class Get extends Base +{ + use HTTP; + + public static function getName() + { + return 'getUsage'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/:functionId/usage') + ->desc('Get function usage') + ->groups(['api', 'functions', 'usage']) + ->label('scope', 'functions.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'getUsage', + description: <<<EOT + 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. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_FUNCTION, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $functionId, string $range, Response $response, Database $dbForProject) + { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $periods = Config::getParam('usage', []); + $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), + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $result = $dbForProject->findOne('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', ['inf']) + ]); + + $stats[$metric]['total'] = $result['value'] ?? 0; + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', [$period]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric]['data'] = []; + foreach ($results as $result) { + $stats[$metric]['data'][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['data'] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric]['data'][] = [ + 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + + $buildsTimeTotal = $usage[$metrics[4]]['total'] ?? 0; + $buildsTotal = $usage[$metrics[2]]['total'] ?? 0; + $response->dynamic(new Document([ + 'range' => $range, + 'deploymentsTotal' => $usage[$metrics[0]]['total'], + 'deploymentsStorageTotal' => $usage[$metrics[1]]['total'], + 'buildsTotal' => $usage[$metrics[2]]['total'], + 'buildsSuccessTotal' => $usage[$metrics[9]]['total'], + 'buildsFailedTotal' => $usage[$metrics[10]]['total'], + 'buildsStorageTotal' => $usage[$metrics[3]]['total'], + 'buildsTimeTotal' => $usage[$metrics[4]]['total'], + 'buildsTimeAverage' => $buildsTotal === 0 ? 0 : (int) ($buildsTimeTotal / $buildsTotal), + 'executionsTotal' => $usage[$metrics[5]]['total'], + 'executionsTimeTotal' => $usage[$metrics[6]]['total'], + 'buildsMbSecondsTotal' => $usage[$metrics[7]]['total'], + 'executionsMbSecondsTotal' => $usage[$metrics[8]]['total'], + 'deployments' => $usage[$metrics[0]]['data'], + 'deploymentsStorage' => $usage[$metrics[1]]['data'], + 'builds' => $usage[$metrics[2]]['data'], + 'buildsStorage' => $usage[$metrics[3]]['data'], + 'buildsTime' => $usage[$metrics[4]]['data'], + 'executions' => $usage[$metrics[5]]['data'], + 'executionsTime' => $usage[$metrics[6]]['data'], + 'buildsMbSeconds' => $usage[$metrics[7]]['data'], + 'executionsMbSeconds' => $usage[$metrics[8]]['data'], + 'buildsSuccess' => $usage[$metrics[9]]['data'], + 'buildsFailed' => $usage[$metrics[10]]['data'], + ]), Response::MODEL_USAGE_FUNCTION); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php new file mode 100644 index 0000000000..e4a7c01bdf --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/XList.php @@ -0,0 +1,148 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Usage; + +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\WhiteList; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'getFunctionsUsage'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/usage') + ->desc('Get functions usage') + ->groups(['api', 'functions', 'usage']) + ->label('scope', 'functions.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('sdk', new Method( + namespace: 'functions', + name: 'listUsage', + description: <<<EOT + 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. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_FUNCTIONS, + ) + ] + )) + ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $range, Response $response, Database $dbForProject) + { + $periods = Config::getParam('usage', []); + $stats = $usage = []; + $days = $periods[$range]; + $metrics = [ + METRIC_FUNCTIONS, + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_DEPLOYMENTS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_STORAGE), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_COMPUTE), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_EXECUTIONS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_SUCCESS), + str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_FAILED), + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $result = $dbForProject->findOne('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', ['inf']) + ]); + + $stats[$metric]['total'] = $result['value'] ?? 0; + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', [$period]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric]['data'] = []; + foreach ($results as $result) { + $stats[$metric]['data'][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['data'] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric]['data'][] = [ + 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + $response->dynamic(new Document([ + 'range' => $range, + 'functionsTotal' => $usage[$metrics[0]]['total'], + 'deploymentsTotal' => $usage[$metrics[1]]['total'], + 'deploymentsStorageTotal' => $usage[$metrics[2]]['total'], + 'buildsTotal' => $usage[$metrics[3]]['total'], + 'buildsStorageTotal' => $usage[$metrics[4]]['total'], + 'buildsTimeTotal' => $usage[$metrics[5]]['total'], + 'executionsTotal' => $usage[$metrics[6]]['total'], + 'executionsTimeTotal' => $usage[$metrics[7]]['total'], + 'buildsMbSecondsTotal' => $usage[$metrics[8]]['total'], + 'executionsMbSecondsTotal' => $usage[$metrics[9]]['total'], + 'buildsSuccessTotal' => $usage[$metrics[10]]['total'], + 'buildsFailedTotal' => $usage[$metrics[11]]['total'], + 'functions' => $usage[$metrics[0]]['data'], + 'deployments' => $usage[$metrics[1]]['data'], + 'deploymentsStorage' => $usage[$metrics[2]]['data'], + 'builds' => $usage[$metrics[3]]['data'], + 'buildsStorage' => $usage[$metrics[4]]['data'], + 'buildsTime' => $usage[$metrics[5]]['data'], + 'executions' => $usage[$metrics[6]]['data'], + 'executionsTime' => $usage[$metrics[7]]['data'], + 'buildsMbSeconds' => $usage[$metrics[8]]['data'], + 'executionsMbSeconds' => $usage[$metrics[9]]['data'], + 'buildsSuccess' => $usage[$metrics[10]]['data'], + 'buildsFailed' => $usage[$metrics[11]]['data'], + ]), Response::MODEL_USAGE_FUNCTIONS); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php new file mode 100644 index 0000000000..91f2870ce1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -0,0 +1,127 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Variables; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\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; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; + +class Create extends Base +{ + use HTTP; + + public static function getName() + { + return 'createVariable'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/functions/:functionId/variables') + ->desc('Create variable') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('audits.event', 'variable.create') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'createVariable', + description: <<<EOT + Create a new function environment variable. These variables can be accessed in the function at runtime as environment variables. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_VARIABLE, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function unique ID.', false) + ->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false) + ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false) + ->param('secret', true, new Boolean(), 'Secret variables can be updated or deleted, but only functions can read them during build and runtime.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->inject('project') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $key, + string $value, + bool $secret, + Response $response, + Database $dbForProject, + Database $dbForPlatform, + Document $project + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $variableId = ID::unique(); + + $teamId = $project->getAttribute('teamId', ''); + $variable = new Document([ + '$id' => $variableId, + '$permissions' => [ + Permission::read(Role::team(ID::custom($teamId))), + Permission::update(Role::team(ID::custom($teamId), 'owner')), + Permission::update(Role::team(ID::custom($teamId), 'developer')), + Permission::delete(Role::team(ID::custom($teamId), 'owner')), + Permission::delete(Role::team(ID::custom($teamId), 'developer')), + ], + 'resourceInternalId' => $function->getInternalId(), + 'resourceId' => $function->getId(), + 'resourceType' => 'function', + 'key' => $key, + 'value' => $value, + 'secret' => $secret, + 'search' => implode(' ', [$variableId, $function->getId(), $key, 'function']), + ]); + + try { + $variable = $dbForProject->createDocument('variables', $variable); + } catch (DuplicateException $th) { + throw new Exception(Exception::VARIABLE_ALREADY_EXISTS); + } + + $dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false)); + + // Inform scheduler to pull the latest changes + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule + ->setAttribute('resourceUpdatedAt', DateTime::now()) + ->setAttribute('schedule', $function->getAttribute('schedule')) + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($variable, Response::MODEL_VARIABLE); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php new file mode 100644 index 0000000000..13bc8c41b6 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -0,0 +1,98 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Variables; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Delete extends Base +{ + use HTTP; + + public static function getName() + { + return 'deleteVariable'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/functions/:functionId/variables/:variableId') + ->desc('Delete variable') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('audits.event', 'variable.delete') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'deleteVariable', + description: <<<EOT + Delete a variable by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('functionId', '', new UID(), 'Function unique ID.', false) + ->param('variableId', '', new UID(), 'Variable unique ID.', false) + ->inject('response') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $variableId, + Response $response, + Database $dbForProject, + Database $dbForPlatform + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $variable = $dbForProject->getDocument('variables', $variableId); + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function') { + throw new Exception(Exception::VARIABLE_NOT_FOUND); + } + + if ($variable === false || $variable->isEmpty()) { + throw new Exception(Exception::VARIABLE_NOT_FOUND); + } + + $dbForProject->deleteDocument('variables', $variable->getId()); + + $dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false)); + + // Inform scheduler to pull the latest changes + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule + ->setAttribute('resourceUpdatedAt', DateTime::now()) + ->setAttribute('schedule', $function->getAttribute('schedule')) + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php new file mode 100644 index 0000000000..eeb5c51f33 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php @@ -0,0 +1,82 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Variables; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Get extends Base +{ + use HTTP; + + public static function getName() + { + return 'getVariable'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/:functionId/variables/:variableId') + ->desc('Get variable') + ->groups(['api', 'functions']) + ->label('scope', 'functions.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label( + 'sdk', + new Method( + namespace: 'functions', + name: 'getVariable', + description: <<<EOT + Get a variable by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE, + ) + ], + ) + ) + ->param('functionId', '', new UID(), 'Function unique ID.', false) + ->param('variableId', '', new UID(), 'Variable unique ID.', false) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $functionId, string $variableId, Response $response, Database $dbForProject) + { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $variable = $dbForProject->getDocument('variables', $variableId); + if ( + $variable === false || + $variable->isEmpty() || + $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || + $variable->getAttribute('resourceType') !== 'function' + ) { + throw new Exception(Exception::VARIABLE_NOT_FOUND); + } + + if ($variable === false || $variable->isEmpty()) { + throw new Exception(Exception::VARIABLE_NOT_FOUND); + } + + $response->dynamic($variable, Response::MODEL_VARIABLE); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php new file mode 100644 index 0000000000..6f1bab8401 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -0,0 +1,115 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Variables; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\DateTime; +use Utopia\Database\Exception\Duplicate as DuplicateException; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; + +class Update extends Base +{ + use HTTP; + + public static function getName() + { + return 'updateVariable'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/functions/:functionId/variables/:variableId') + ->desc('Update variable') + ->groups(['api', 'functions']) + ->label('scope', 'functions.write') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label('audits.event', 'variable.update') + ->label('audits.resource', 'function/{request.functionId}') + ->label('sdk', new Method( + namespace: 'functions', + name: 'updateVariable', + description: <<<EOT + Update variable by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE, + ) + ] + )) + ->param('functionId', '', new UID(), 'Function unique ID.', false) + ->param('variableId', '', new UID(), 'Variable unique ID.', false) + ->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false) + ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true) + ->param('secret', null, new Boolean(), 'Secret variables can be updated or deleted, but only functions can read them during build and runtime.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action( + string $functionId, + string $variableId, + string $key, + ?string $value, + ?bool $secret, + Response $response, + Database $dbForProject, + Database $dbForPlatform + ) { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $variable = $dbForProject->getDocument('variables', $variableId); + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function') { + throw new Exception(Exception::VARIABLE_NOT_FOUND); + } + + if ($variable->getAttribute('secret') === true && $secret === false) { + throw new Exception(Exception::VARIABLE_CANNOT_UNSET_SECRET); + } + + $variable + ->setAttribute('key', $key) + ->setAttribute('value', $value ?? $variable->getAttribute('value')) + ->setAttribute('secret', $secret ?? $variable->getAttribute('secret')) + ->setAttribute('search', implode(' ', [$variableId, $function->getId(), $key, 'function'])); + + try { + $dbForProject->updateDocument('variables', $variable->getId(), $variable); + } catch (DuplicateException $th) { + throw new Exception(Exception::VARIABLE_ALREADY_EXISTS); + } + + $dbForProject->updateDocument('functions', $function->getId(), $function->setAttribute('live', false)); + + // Inform scheduler to pull the latest changes + $schedule = $dbForPlatform->getDocument('schedules', $function->getAttribute('scheduleId')); + $schedule + ->setAttribute('resourceUpdatedAt', DateTime::now()) + ->setAttribute('schedule', $function->getAttribute('schedule')) + ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deploymentId'))); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + + $response->dynamic($variable, Response::MODEL_VARIABLE); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/XList.php new file mode 100644 index 0000000000..000e83a0c9 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/XList.php @@ -0,0 +1,71 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Http\Variables; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listVariables'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/functions/:functionId/variables') + ->desc('List variables') + ->groups(['api', 'functions']) + ->label('scope', 'functions.read') + ->label('resourceType', RESOURCE_TYPE_FUNCTIONS) + ->label( + 'sdk', + new Method( + namespace: 'functions', + name: 'listVariables', + description: <<<EOT + Get a list of all variables of a specific function. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE_LIST, + ) + ], + ) + ) + ->param('functionId', '', new UID(), 'Function unique ID.', false) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $functionId, Response $response, Database $dbForProject) + { + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $response->dynamic(new Document([ + 'variables' => $function->getAttribute('vars', []), + 'total' => \count($function->getAttribute('vars', [])), + ]), Response::MODEL_VARIABLE_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Module.php b/src/Appwrite/Platform/Modules/Functions/Module.php new file mode 100644 index 0000000000..18617bb0c8 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Module.php @@ -0,0 +1,16 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions; + +use Appwrite\Platform\Modules\Functions\Services\Http; +use Appwrite\Platform\Modules\Functions\Services\Workers; +use Utopia\Platform; + +class Module extends Platform\Module +{ + public function __construct() + { + $this->addService('http', new Http()); + $this->addService('workers', new Workers()); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Services/Http.php b/src/Appwrite/Platform/Modules/Functions/Services/Http.php new file mode 100644 index 0000000000..cf47574472 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Services/Http.php @@ -0,0 +1,89 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Services; + +use Appwrite\Platform\Modules\Functions\Http\Deployments\Create as CreateDeployment; +use Appwrite\Platform\Modules\Functions\Http\Deployments\Delete as DeleteDeployment; +use Appwrite\Platform\Modules\Functions\Http\Deployments\Download\Get as DownloadDeployment; +use Appwrite\Platform\Modules\Functions\Http\Deployments\Duplicate\Create as CreateDuplicateDeployment; +use Appwrite\Platform\Modules\Functions\Http\Deployments\Get as GetDeployment; +use Appwrite\Platform\Modules\Functions\Http\Deployments\Status\Update as UpdateDeploymentStatus; +use Appwrite\Platform\Modules\Functions\Http\Deployments\Template\Create as CreateTemplateDeployment; +use Appwrite\Platform\Modules\Functions\Http\Deployments\Vcs\Create as CreateVcsDeployment; +use Appwrite\Platform\Modules\Functions\Http\Deployments\XList as ListDeployments; +use Appwrite\Platform\Modules\Functions\Http\Executions\Create as CreateExecution; +use Appwrite\Platform\Modules\Functions\Http\Executions\Delete as DeleteExecution; +use Appwrite\Platform\Modules\Functions\Http\Executions\Get as GetExecution; +use Appwrite\Platform\Modules\Functions\Http\Executions\XList as ListExecutions; +use Appwrite\Platform\Modules\Functions\Http\Functions\Create as CreateFunction; +use Appwrite\Platform\Modules\Functions\Http\Functions\Delete as DeleteFunction; +use Appwrite\Platform\Modules\Functions\Http\Functions\Deployment\Update as UpdateFunctionDeployment; +use Appwrite\Platform\Modules\Functions\Http\Functions\Get as GetFunction; +use Appwrite\Platform\Modules\Functions\Http\Functions\Update as UpdateFunction; +use Appwrite\Platform\Modules\Functions\Http\Functions\XList as ListFunctions; +use Appwrite\Platform\Modules\Functions\Http\Runtimes\XList as ListRuntimes; +use Appwrite\Platform\Modules\Functions\Http\Specifications\XList as ListSpecifications; +use Appwrite\Platform\Modules\Functions\Http\Templates\Get as GetTemplate; +use Appwrite\Platform\Modules\Functions\Http\Templates\XList as ListTemplates; +use Appwrite\Platform\Modules\Functions\Http\Usage\Get as GetUsage; +use Appwrite\Platform\Modules\Functions\Http\Usage\XList as ListUsage; +use Appwrite\Platform\Modules\Functions\Http\Variables\Create as CreateVariable; +use Appwrite\Platform\Modules\Functions\Http\Variables\Delete as DeleteVariable; +use Appwrite\Platform\Modules\Functions\Http\Variables\Get as GetVariable; +use Appwrite\Platform\Modules\Functions\Http\Variables\Update as UpdateVariable; +use Appwrite\Platform\Modules\Functions\Http\Variables\XList as ListVariables; +use Utopia\Platform\Service; + +class Http extends Service +{ + public function __construct() + { + $this->type = Service::TYPE_HTTP; + + // Functions + $this->addAction(CreateFunction::getName(), new CreateFunction()); + $this->addAction(GetFunction::getName(), new GetFunction()); + $this->addAction(UpdateFunction::getName(), new UpdateFunction()); + $this->addAction(ListFunctions::getName(), new ListFunctions()); + $this->addAction(DeleteFunction::getName(), new DeleteFunction()); + + // Runtimes + $this->addAction(ListRuntimes::getName(), new ListRuntimes()); + + // Specifications + $this->addAction(ListSpecifications::getName(), new ListSpecifications()); + + // Deployments + $this->addAction(CreateDeployment::getName(), new CreateDeployment()); + $this->addAction(GetDeployment::getName(), new GetDeployment()); + $this->addAction(UpdateFunctionDeployment::getName(), new UpdateFunctionDeployment()); + $this->addAction(ListDeployments::getName(), new ListDeployments()); + $this->addAction(DeleteDeployment::getName(), new DeleteDeployment()); + $this->addAction(CreateTemplateDeployment::getName(), new CreateTemplateDeployment()); + $this->addAction(CreateVcsDeployment::getName(), new CreateVcsDeployment()); + $this->addAction(DownloadDeployment::getName(), new DownloadDeployment()); + $this->addAction(CreateDuplicateDeployment::getName(), new CreateDuplicateDeployment()); + $this->addAction(UpdateDeploymentStatus::getName(), new UpdateDeploymentStatus()); + + // Executions + $this->addAction(CreateExecution::getName(), new CreateExecution()); + $this->addAction(GetExecution::getName(), new GetExecution()); + $this->addAction(ListExecutions::getName(), new ListExecutions()); + $this->addAction(DeleteExecution::getName(), new DeleteExecution()); + + // Usage + $this->addAction(GetUsage::getName(), new GetUsage()); + $this->addAction(ListUsage::getName(), new ListUsage()); + + // Variables + $this->addAction(CreateVariable::getName(), new CreateVariable()); + $this->addAction(GetVariable::getName(), new GetVariable()); + $this->addAction(ListVariables::getName(), new ListVariables()); + $this->addAction(UpdateVariable::getName(), new UpdateVariable()); + $this->addAction(DeleteVariable::getName(), new DeleteVariable()); + + // Templates + $this->addAction(GetTemplate::getName(), new GetTemplate()); + $this->addAction(ListTemplates::getName(), new ListTemplates()); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Services/Workers.php b/src/Appwrite/Platform/Modules/Functions/Services/Workers.php new file mode 100644 index 0000000000..61256b6bf9 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Services/Workers.php @@ -0,0 +1,15 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Services; + +use Appwrite\Platform\Modules\Functions\Workers\Builds; +use Utopia\Platform\Service; + +class Workers extends Service +{ + public function __construct() + { + $this->type = Service::TYPE_WORKER; + $this->addAction(Builds::getName(), new Builds()); + } +} diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php new file mode 100644 index 0000000000..5356a746e6 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -0,0 +1,1447 @@ +<?php + +namespace Appwrite\Platform\Modules\Functions\Workers; + +use Ahc\Jwt\JWT; +use Appwrite\Event\Event; +use Appwrite\Event\Func; +use Appwrite\Event\Realtime; +use Appwrite\Event\StatsUsage; +use Appwrite\Event\Webhook; +use Appwrite\Permission; +use Appwrite\Role; +use Appwrite\Utopia\Response\Model\Deployment; +use Appwrite\Vcs\Comment; +use Exception; +use Executor\Executor; +use Swoole\Coroutine as Co; +use Utopia\Cache\Cache; +use Utopia\CLI\Console; +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Exception\Conflict; +use Utopia\Database\Exception\Duplicate; +use Utopia\Database\Exception\Restricted; +use Utopia\Database\Exception\Structure; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Detector\Detection\Rendering\SSR; +use Utopia\Detector\Detection\Rendering\XStatic; +use Utopia\Detector\Detector\Rendering; +use Utopia\Fetch\Client as FetchClient; +use Utopia\Logger\Log; +use Utopia\Platform\Action; +use Utopia\Queue\Message; +use Utopia\Storage\Compression\Compression; +use Utopia\Storage\Device; +use Utopia\Storage\Device\Local; +use Utopia\System\System; +use Utopia\VCS\Adapter\Git\GitHub; + +use function Swoole\Coroutine\batch; + +class Builds extends Action +{ + public static function getName(): string + { + return 'builds'; + } + + /** + * @throws Exception + */ + public function __construct() + { + $this + ->desc('Builds worker') + ->inject('message') + ->inject('project') + ->inject('dbForPlatform') + ->inject('queueForEvents') + ->inject('queueForWebhooks') + ->inject('queueForFunctions') + ->inject('queueForRealtime') + ->inject('queueForStatsUsage') + ->inject('cache') + ->inject('dbForProject') + ->inject('deviceForFunctions') + ->inject('deviceForSites') + ->inject('isResourceBlocked') + ->inject('deviceForFiles') + ->inject('log') + ->inject('executor') + ->callback([$this, 'action']); + } + + /** + * @param Message $message + * @param Document $project + * @param Database $dbForPlatform + * @param Event $queueForEvents + * @param Webhook $queueForWebhooks + * @param Func $queueForFunctions + * @param Realtime $queueForRealtime + * @param StatsUsage $queueForStatsUsage + * @param Cache $cache + * @param Database $dbForProject + * @param Device $deviceForFunctions + * @param Device $deviceForSites + * @param Device $deviceForFiles + * @param Log $log + * @param Executor $executor + * @return void + * @throws \Utopia\Database\Exception + */ + public function action( + Message $message, + Document $project, + Database $dbForPlatform, + Event $queueForEvents, + Webhook $queueForWebhooks, + Func $queueForFunctions, + Realtime $queueForRealtime, + StatsUsage $queueForStatsUsage, + Cache $cache, + Database $dbForProject, + Device $deviceForFunctions, + Device $deviceForSites, + callable $isResourceBlocked, + Device $deviceForFiles, + Log $log, + Executor $executor + ): void { + $payload = $message->getPayload() ?? []; + + if (empty($payload)) { + throw new \Exception('Missing payload'); + } + + $type = $payload['type'] ?? ''; + $resource = new Document($payload['resource'] ?? []); + $deployment = new Document($payload['deployment'] ?? []); + $template = new Document($payload['template'] ?? []); + + $log->addTag('projectId', $project->getId()); + $log->addTag('type', $type); + + switch ($type) { + case BUILD_TYPE_DEPLOYMENT: + case BUILD_TYPE_RETRY: + Console::info('Creating build for deployment: ' . $deployment->getId()); + $github = new GitHub($cache); + $this->buildDeployment( + $deviceForFunctions, + $deviceForSites, + $deviceForFiles, + $queueForWebhooks, + $queueForFunctions, + $queueForRealtime, + $queueForEvents, + $queueForStatsUsage, + $dbForPlatform, + $dbForProject, + $github, + $project, + $resource, + $deployment, + $template, + $isResourceBlocked, + $log, + $executor + ); + break; + + default: + throw new \Exception('Invalid build type'); + } + } + + /** + * @param Device $deviceForFunctions + * @param Device $deviceForSites + * @param Device $deviceForFiles + * @param Webhook $queueForWebhooks + * @param Func $queueForFunctions + * @param Realtime $queueForRealtime + * @param Event $queueForEvents + * @param StatsUsage $queueForStatsUsage + * @param Database $dbForPlatform + * @param Database $dbForProject + * @param GitHub $github + * @param Document $project + * @param Document $resource + * @param Document $deployment + * @param Document $template + * @param Log $log + * @param Executor $executor + * @return void + * @throws \Utopia\Database\Exception + * + * @throws Exception + */ + protected function buildDeployment( + Device $deviceForFunctions, + Device $deviceForSites, + Device $deviceForFiles, + Webhook $queueForWebhooks, + Func $queueForFunctions, + Realtime $queueForRealtime, + Event $queueForEvents, + StatsUsage $queueForStatsUsage, + Database $dbForPlatform, + Database $dbForProject, + GitHub $github, + Document $project, + Document $resource, + Document $deployment, + Document $template, + callable $isResourceBlocked, + Log $log, + Executor $executor + ): void { + $resourceKey = match ($resource->getCollection()) { + 'functions' => 'functionId', + 'sites' => 'siteId', + default => throw new \Exception('Invalid resource type') + }; + + $device = match ($resource->getCollection()) { + 'sites' => $deviceForSites, + 'functions' => $deviceForFunctions, + }; + + $log->addTag($resourceKey, $resource->getId()); + + $resource = $dbForProject->getDocument($resource->getCollection(), $resource->getId()); + if ($resource->isEmpty()) { + throw new \Exception('Resource not found'); + } + + if ($isResourceBlocked($project, $resourceKey === 'functions' ? RESOURCE_TYPE_FUNCTIONS : RESOURCE_TYPE_SITES, $resource->getId())) { + throw new \Exception('Resource is blocked'); + } + + $log->addTag('deploymentId', $deployment->getId()); + + $deployment = $dbForProject->getDocument('deployments', $deployment->getId()); + if ($deployment->isEmpty()) { + throw new \Exception('Deployment not found'); + } + + if ($resource->getCollection() === 'functions' && empty($deployment->getAttribute('entrypoint', ''))) { + throw new \Exception('Entrypoint for your Appwrite Function is missing. Please specify it when making deployment or update the entrypoint under your function\'s "Settings" > "Configuration" > "Entrypoint".'); + } + + $version = $this->getVersion($resource); + $runtime = $this->getRuntime($resource, $version); + + $spec = Config::getParam('specifications')[$resource->getAttribute('specification', APP_COMPUTE_SPECIFICATION_DEFAULT)]; + + if ($resource->getCollection() === 'functions' && \is_null($runtime)) { + throw new \Exception('Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported'); + } + + // Realtime preparation + $event = "{$resource->getCollection()}.[{$resourceKey}].deployments.[deploymentId].update"; + $queueForRealtime + ->setSubscribers(['console']) + ->setProject($project) + ->setEvent($event) + ->setParam($resourceKey, $resource->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $startTime = DateTime::now(); + $durationStart = \microtime(true); + + if ($deployment->getAttribute('status') === 'canceled') { + Console::info('Build has been canceled'); + return; + } + + $deploymentId = $deployment->getId(); + + $deployment->setAttribute('buildStartAt', $startTime); + $deployment->setAttribute('status', 'processing'); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); + } + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + + $source = $deployment->getAttribute('sourcePath', ''); + $installationId = $deployment->getAttribute('installationId', ''); + $providerRepositoryId = $deployment->getAttribute('providerRepositoryId', ''); + $providerCommitHash = $deployment->getAttribute('providerCommitHash', ''); + $isVcsEnabled = !empty($providerRepositoryId); + $owner = ''; + $repositoryName = ''; + + if ($isVcsEnabled) { + $installation = $dbForPlatform->getDocument('installations', $installationId); + $providerInstallationId = $installation->getAttribute('providerInstallationId'); + $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); + $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); + + $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); + } + + try { + if (!$isVcsEnabled) { + // Non-VCS + Template + $templateRepositoryName = $template->getAttribute('repositoryName', ''); + $templateOwnerName = $template->getAttribute('ownerName', ''); + $templateVersion = $template->getAttribute('version', ''); + + $templateRootDirectory = $template->getAttribute('rootDirectory', ''); + $templateRootDirectory = \rtrim($templateRootDirectory, '/'); + $templateRootDirectory = \ltrim($templateRootDirectory, '.'); + $templateRootDirectory = \ltrim($templateRootDirectory, '/'); + + if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateVersion)) { + $stdout = ''; + $stderr = ''; + + // Clone template repo + $tmpTemplateDirectory = '/tmp/builds/' . $deploymentId . '-template'; + $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory); + $exit = Console::execute($gitCloneCommandForTemplate, '', $stdout, $stderr); + + if ($exit !== 0) { + throw new \Exception('Unable to clone code repository: ' . $stderr); + } + + Console::execute('find ' . \escapeshellarg($tmpTemplateDirectory) . ' -type d -name ".git" -exec rm -rf {} +', '', $stdout, $stderr); + + // Ensure directories + Console::execute('mkdir -p ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory), '', $stdout, $stderr); + + $tmpPathFile = $tmpTemplateDirectory . '/code.tar.gz'; + + $localDevice = new Local(); + + if (substr($tmpTemplateDirectory, -1) !== '/') { + $tmpTemplateDirectory .= '/'; + } + + $tarParamDirectory = \escapeshellarg($tmpTemplateDirectory . (empty($templateRootDirectory) ? '' : '/' . $templateRootDirectory)); + Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellcmd($tarParamDirectory) . ' .', '', $stdout, $stderr); // TODO: Replace escapeshellcmd with escapeshellarg if we find a way that doesnt break syntax + + $source = $device->getPath($deployment->getId() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); + $result = $localDevice->transfer($tmpPathFile, $source, $device); + + if (!$result) { + throw new \Exception("Unable to move file"); + } + + Console::execute('rm -rf ' . \escapeshellarg($tmpTemplateDirectory), '', $stdout, $stderr); + + $directorySize = $device->getFileSize($source); + $deployment + ->setAttribute('sourcePath', $source) + ->setAttribute('sourceSize', $directorySize) + ->setAttribute('totalSize', $directorySize); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + } + } elseif ($isVcsEnabled) { + // VCS and VCS+Temaplte + $tmpDirectory = '/tmp/builds/' . $deploymentId . '/code'; + $rootDirectory = $resource->getAttribute('providerRootDirectory', ''); + $rootDirectory = \rtrim($rootDirectory, '/'); + $rootDirectory = \ltrim($rootDirectory, '.'); + $rootDirectory = \ltrim($rootDirectory, '/'); + + $owner = $github->getOwnerName($providerInstallationId); + $repositoryName = $github->getRepositoryName($providerRepositoryId); + + $cloneOwner = $deployment->getAttribute('providerRepositoryOwner', $owner); + $cloneRepository = $deployment->getAttribute('providerRepositoryName', $repositoryName); + + $branchName = $deployment->getAttribute('providerBranch'); + $commitHash = $deployment->getAttribute('providerCommitHash', ''); + + $cloneVersion = $branchName; + $cloneType = GitHub::CLONE_TYPE_BRANCH; + if (!empty($commitHash)) { + $cloneVersion = $commitHash; + $cloneType = GitHub::CLONE_TYPE_COMMIT; + } + + $gitCloneCommand = $github->generateCloneCommand($cloneOwner, $cloneRepository, $cloneVersion, $cloneType, $tmpDirectory, $rootDirectory); + $stdout = ''; + $stderr = ''; + + Console::execute('mkdir -p ' . \escapeshellarg('/tmp/builds/' . $deploymentId), '', $stdout, $stderr); + + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { + Console::info('Build has been canceled'); + return; + } + + $exit = Console::execute($gitCloneCommand, '', $stdout, $stderr); + + if ($exit !== 0) { + throw new \Exception('Unable to clone code repository: ' . $stderr); + } + + // Local refactoring for function folder with spaces + if (str_contains($rootDirectory, ' ')) { + $rootDirectoryWithoutSpaces = str_replace(' ', '', $rootDirectory); + $from = $tmpDirectory . '/' . $rootDirectory; + $to = $tmpDirectory . '/' . $rootDirectoryWithoutSpaces; + $exit = Console::execute('mv "' . \escapeshellarg($from) . '" "' . \escapeshellarg($to) . '"', '', $stdout, $stderr); + + if ($exit !== 0) { + throw new \Exception('Unable to move function with spaces' . $stderr); + } + $rootDirectory = $rootDirectoryWithoutSpaces; + } + + + // Build from template + $templateRepositoryName = $template->getAttribute('repositoryName', ''); + $templateOwnerName = $template->getAttribute('ownerName', ''); + $templateVersion = $template->getAttribute('version', ''); + + $templateRootDirectory = $template->getAttribute('rootDirectory', ''); + $templateRootDirectory = \rtrim($templateRootDirectory, '/'); + $templateRootDirectory = \ltrim($templateRootDirectory, '.'); + $templateRootDirectory = \ltrim($templateRootDirectory, '/'); + + if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateVersion)) { + // Clone template repo + $tmpTemplateDirectory = '/tmp/builds/' . $deploymentId . '/template'; + + $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory); + $exit = Console::execute($gitCloneCommandForTemplate, '', $stdout, $stderr); + + if ($exit !== 0) { + throw new \Exception('Unable to clone code repository: ' . $stderr); + } + + // Ensure directories + Console::execute('mkdir -p ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory), '', $stdout, $stderr); + Console::execute('mkdir -p ' . \escapeshellarg($tmpDirectory . '/' . $rootDirectory), '', $stdout, $stderr); + + // Merge template into user repo + Console::execute('rsync -av --exclude \'.git\' ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory . '/') . ' ' . \escapeshellarg($tmpDirectory . '/' . $rootDirectory), '', $stdout, $stderr); + + // Commit and push + $exit = Console::execute('git config --global user.email "team@appwrite.io" && git config --global user.name "Appwrite" && cd ' . \escapeshellarg($tmpDirectory) . ' && git add . && git commit -m "Create ' . \escapeshellarg($resource->getAttribute('name', '')) . ' function" && git push origin ' . \escapeshellarg($branchName), '', $stdout, $stderr); + + if ($exit !== 0) { + throw new \Exception('Unable to push code repository: ' . $stderr); + } + + $exit = Console::execute('cd ' . \escapeshellarg($tmpDirectory) . ' && git rev-parse HEAD', '', $stdout, $stderr); + + if ($exit !== 0) { + throw new \Exception('Unable to get vcs commit SHA: ' . $stderr); + } + + $providerCommitHash = \trim($stdout); + $authorUrl = "https://github.com/$cloneOwner"; + + $deployment->setAttribute('providerCommitHash', $providerCommitHash ?? ''); + $deployment->setAttribute('providerCommitAuthorUrl', $authorUrl); + $deployment->setAttribute('providerCommitAuthor', 'Appwrite'); + $deployment->setAttribute('providerCommitMessage', "Create '" . $resource->getAttribute('name', '') . "' function"); + $deployment->setAttribute('providerCommitUrl', "https://github.com/$cloneOwner/$cloneRepository/commit/$providerCommitHash"); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + } + + $tmpPath = '/tmp/builds/' . $deploymentId; + $tmpPathFile = $tmpPath . '/code.tar.gz'; + $localDevice = new Local(); + + if (substr($tmpDirectory, -1) !== '/') { + $tmpDirectory .= '/'; + } + + $directorySize = $localDevice->getDirectorySize($tmpDirectory); + $sizeLimit = (int)System::getEnv('_APP_COMPUTE_SIZE_LIMIT', '30000000'); + + if ($directorySize > $sizeLimit) { + throw new \Exception('Repository directory size should be less than ' . number_format($sizeLimit / 1048576, 2) . ' MBs.'); + } + + Console::execute('find ' . \escapeshellarg($tmpDirectory) . ' -type d -name ".git" -exec rm -rf {} +', '', $stdout, $stderr); + + $tarParamDirectory = '/tmp/builds/' . $deploymentId . '/code' . (empty($rootDirectory) ? '' : '/' . $rootDirectory); + Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellcmd($tarParamDirectory) . ' .', '', $stdout, $stderr); // TODO: Replace escapeshellcmd with escapeshellarg if we find a way that doesnt break syntax + + $source = $device->getPath($deployment->getId() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); + $result = $localDevice->transfer($tmpPathFile, $source, $device); + + if (!$result) { + throw new \Exception("Unable to move file"); + } + + Console::execute('rm -rf ' . \escapeshellarg($tmpPath), '', $stdout, $stderr); + + $directorySize = $device->getFileSize($source); + + $deployment + ->setAttribute('sourcePath', $source) + ->setAttribute('sourceSize', $directorySize) + ->setAttribute('totalSize', $directorySize); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + + $this->runGitAction('processing', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform); + } + + /** Request the executor to build the code... */ + $deployment->setAttribute('status', 'building'); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); + } + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + + if ($isVcsEnabled) { + $this->runGitAction('building', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform); + } + + $deploymentModel = new Deployment(); + $deploymentUpdate = + $queueForEvents + ->setProject($project) + ->setEvent("{$resource->getCollection()}.[{$resourceKey}].deployments.[deploymentId].update") + ->setParam($resourceKey, $resource->getId()) + ->setParam('deploymentId', $deployment->getId()) + ->setPayload($deployment->getArrayCopy(array_keys($deploymentModel->getRules()))); + + /** Trigger Webhook */ + $queueForWebhooks + ->from($deploymentUpdate) + ->trigger(); + + /** Trigger Functions */ + $queueForFunctions + ->from($deploymentUpdate) + ->trigger(); + + /** Trigger Realtime Event */ + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + + $vars = []; + + // Shared vars + foreach ($resource->getAttribute('varsProject', []) as $var) { + $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); + } + + // Function vars + foreach ($resource->getAttribute('vars', []) as $var) { + $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); + } + + // Some runtimes/frameworks can't compile with less memory than this + $minMemory = $resource->getCollection() === 'sites' ? 2048 : 1024; + + if ($resource->getAttribute('framework', '') === 'analog') { + $minMemory = 4096; + } + + $cpus = $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT; + $memory = max($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT, $minMemory); + $timeout = (int) System::getEnv('_APP_COMPUTE_BUILD_TIMEOUT', 900); + + + $jwtExpiry = (int)System::getEnv('_APP_COMPUTE_BUILD_TIMEOUT', 900); + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $jwtExpiry, 0); + + $apiKey = $jwtObj->encode([ + 'projectId' => $project->getId(), + 'scopes' => $resource->getAttribute('scopes', []) + ]); + + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $hostname = System::getEnv('_APP_DOMAIN'); + $endpoint = $protocol . '://' . $hostname . "/v1"; + + // Appwrite vars + $vars = \array_merge($vars, [ + 'APPWRITE_VERSION' => APP_VERSION_STABLE, + 'APPWRITE_REGION' => $project->getAttribute('region'), + 'APPWRITE_DEPLOYMENT_TYPE' => $deployment->getAttribute('type', ''), + 'APPWRITE_VCS_REPOSITORY_ID' => $deployment->getAttribute('providerRepositoryId', ''), + 'APPWRITE_VCS_REPOSITORY_NAME' => $deployment->getAttribute('providerRepositoryName', ''), + 'APPWRITE_VCS_REPOSITORY_OWNER' => $deployment->getAttribute('providerRepositoryOwner', ''), + 'APPWRITE_VCS_REPOSITORY_URL' => $deployment->getAttribute('providerRepositoryUrl', ''), + 'APPWRITE_VCS_REPOSITORY_BRANCH' => $deployment->getAttribute('providerBranch', ''), + 'APPWRITE_VCS_REPOSITORY_BRANCH_URL' => $deployment->getAttribute('providerBranchUrl', ''), + 'APPWRITE_VCS_COMMIT_HASH' => $deployment->getAttribute('providerCommitHash', ''), + 'APPWRITE_VCS_COMMIT_MESSAGE' => $deployment->getAttribute('providerCommitMessage', ''), + 'APPWRITE_VCS_COMMIT_URL' => $deployment->getAttribute('providerCommitUrl', ''), + 'APPWRITE_VCS_COMMIT_AUTHOR_NAME' => $deployment->getAttribute('providerCommitAuthor', ''), + 'APPWRITE_VCS_COMMIT_AUTHOR_URL' => $deployment->getAttribute('providerCommitAuthorUrl', ''), + 'APPWRITE_VCS_ROOT_DIRECTORY' => $deployment->getAttribute('providerRootDirectory', ''), + ]); + + switch ($resource->getCollection()) { + case 'functions': + $vars = [ + ...$vars, + 'APPWRITE_FUNCTION_API_ENDPOINT' => $endpoint, + 'APPWRITE_FUNCTION_API_KEY' => API_KEY_DYNAMIC . '_' . $apiKey, + 'APPWRITE_FUNCTION_ID' => $resource->getId(), + 'APPWRITE_FUNCTION_NAME' => $resource->getAttribute('name'), + 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), + 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), + 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', + 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', + 'APPWRITE_FUNCTION_CPUS' => $cpus, + 'APPWRITE_FUNCTION_MEMORY' => $memory, + ]; + break; + case 'sites': + $vars = [ + ...$vars, + 'APPWRITE_SITE_API_ENDPOINT' => $endpoint, + 'APPWRITE_SITE_API_KEY' => API_KEY_DYNAMIC . '_' . $apiKey, + 'APPWRITE_SITE_ID' => $resource->getId(), + 'APPWRITE_SITE_NAME' => $resource->getAttribute('name'), + 'APPWRITE_SITE_DEPLOYMENT' => $deployment->getId(), + 'APPWRITE_SITE_PROJECT_ID' => $project->getId(), + 'APPWRITE_SITE_RUNTIME_NAME' => $runtime['name'] ?? '', + 'APPWRITE_SITE_RUNTIME_VERSION' => $runtime['version'] ?? '', + 'APPWRITE_SITE_CPUS' => $cpus, + 'APPWRITE_SITE_MEMORY' => $memory, + ]; + break; + } + + $command = $this->getCommand( + resource: $resource, + deployment: $deployment + ); + + $response = null; + $err = null; + + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { + Console::info('Build has been canceled'); + return; + } + + $isCanceled = false; + + Co::join([ + Co\go(function () use ($executor, &$response, $project, $deployment, $source, $resource, $runtime, $vars, $command, $cpus, $memory, $timeout, &$err, $version) { + try { + if ($version === 'v2') { + $command = 'tar -zxf /tmp/code.tar.gz -C /usr/code && cd /usr/local/src/ && ./build.sh'; + } else { + $command = 'tar -zxf /tmp/code.tar.gz -C /mnt/code && helpers/build.sh ' . \trim(\escapeshellarg($command)); + } + + $response = $executor->createRuntime( + deploymentId: $deployment->getId(), + projectId: $project->getId(), + source: $source, + image: $runtime['image'], + version: $version, + cpus: $cpus, + memory: $memory, + timeout: $timeout, + remove: false, + entrypoint: $deployment->getAttribute('entrypoint', ''), + destination: APP_STORAGE_BUILDS . "/app-{$project->getId()}", + variables: $vars, + command: $command, + outputDirectory: $resource->getAttribute('outputDirectory', '') + ); + } catch (\Throwable $error) { + $err = $error; + } + }), + Co\go(function () use ($executor, $project, &$deployment, &$response, $dbForProject, $timeout, &$err, $queueForRealtime, &$isCanceled) { + try { + $executor->getLogs( + deploymentId: $deployment->getId(), + projectId: $project->getId(), + timeout: $timeout, + callback: function ($logs) use (&$response, &$err, $dbForProject, &$isCanceled, &$deployment, $queueForRealtime) { + if ($isCanceled) { + return; + } + + // If we have response or error from concurrent coroutine, we already have latest logs + if ($response === null && $err === null) { + $deployment = $dbForProject->getDocument('deployments', $deployment->getId()); + + if ($deployment->getAttribute('status') === 'canceled') { + $isCanceled = true; + Console::info('Ignoring realtime logs because build has been canceled'); + return; + } + + // Get only valid UTF8 part - removes leftover half-multibytes causing SQL errors + $logs = \mb_substr($logs, 0, null, 'UTF-8'); + + $currentLogs = $deployment->getAttribute('buildLogs', ''); + + $streamLogs = \str_replace("\\n", "{APPWRITE_LINEBREAK_PLACEHOLDER}", $logs); + foreach (\explode("\n", $streamLogs) as $streamLog) { + if (empty($streamLog)) { + continue; + } + + $streamLog = \str_replace("{APPWRITE_LINEBREAK_PLACEHOLDER}", "\n", $streamLog); + $streamParts = \explode(" ", $streamLog, 2); + + // TODO: use part[0] as timestamp when switching to dbForLogs for build logs + $currentLogs .= $streamParts[1]; + } + + $deployment = $deployment->setAttribute('buildLogs', $currentLogs); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + } + } + ); + } catch (\Throwable $error) { + if (empty($err)) { + $err = $error; + } + } + }), + ]); + + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { + Console::info('Build has been canceled'); + return; + } + + if ($err) { + throw $err; + } + + $endTime = DateTime::now(); + $durationEnd = \microtime(true); + + $buildSizeLimit = (int)System::getEnv('_APP_COMPUTE_BUILD_SIZE_LIMIT', '2000000000'); + if ($response['size'] > $buildSizeLimit) { + throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / 1048576, 2) . ' MBs.'); + } + + if ($resource->getCollection() === 'sites') { + // TODO: Refactor with structured command in future, using utopia library (CLI) + $listFilesCommand = "cd /usr/local/build && cd " . \escapeshellarg($resource->getAttribute('outputDirectory', './')) . " && find . -name 'node_modules' -prune -o -type f -print"; + $command = $executor->createCommand( + deploymentId: $deployment->getId(), + projectId: $project->getId(), + command: $listFilesCommand, + timeout: 15 + ); + + $files = \explode("\n", $command['output']); // Parse output + $files = \array_filter($files); // Remove empty + $files = \array_map(fn ($file) => \trim($file), $files); // Remove whitepsaces + $files = \array_map(fn ($file) => \str_starts_with($file, './') ? \substr($file, 2) : $file, $files); // Remove beginning ./ + + $detector = new Rendering($files, $resource->getAttribute('framework', '')); + $detector + ->addOption(new SSR()) + ->addOption(new XStatic()); + $detection = $detector->detect(); + + $adapter = $resource->getAttribute('adapter', ''); + + if (empty($adapter)) { + $resource->setAttribute('adapter', $detection->getName()); + $resource->setAttribute('fallbackFile', $detection->getFallbackFile() ?? ''); + $resource = $dbForProject->updateDocument('sites', $resource->getId(), $resource); + + $deployment->setAttribute('adapter', $detection->getName()); + $deployment->setAttribute('fallbackFile', $detection->getFallbackFile() ?? ''); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + } elseif ($adapter === 'ssr' && $detection->getName() === 'static') { + throw new \Exception('Adapter mismatch. Detected: ' . $detection->getName() . ' does not match with the set adapter: ' . $adapter); + } + } + + $executor->deleteRuntime($project->getId(), $deployment->getId(), '-build'); + + /** Update the build document */ + $deployment->setAttribute('buildStartAt', DateTime::format((new \DateTime())->setTimestamp(floor($response['startTime'])))); + $deployment->setAttribute('buildEndAt', $endTime); + $deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart))); + $deployment->setAttribute('buildPath', $response['path']); + $deployment->setAttribute('buildSize', $response['size']); + $deployment->setAttribute('totalSize', $deployment->getAttribute('buildSize', 0) + $deployment->getAttribute('sourceSize', 0)); + + $logs = ''; + foreach ($response['output'] as $log) { + $logs .= $log['content']; + } + + if ($resource->getCollection() === 'sites') { + $date = \date('H:i:s'); + $logs .= "[$date] [appwrite] Screenshot capturing started. \n"; + } + + $deployment->setAttribute('buildLogs', $logs); + + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + + /** Screenshot site */ + if ($resource->getCollection() === 'sites') { + try { + $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + Query::equal("projectInternalId", [$project->getInternalId()]), + Query::equal("type", ["deployment"]), + Query::equal('deploymentInternalId', [$deployment->getInternalId()]), + ])); + + if ($rule->isEmpty()) { + throw new \Exception("Rule for build not found"); + } + + $client = new FetchClient(); + $client->setTimeout(\intval($resource->getAttribute('timeout', '15'))); + $client->addHeader('content-type', FetchClient::CONTENT_TYPE_APPLICATION_JSON); + + $bucket = Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + + $configs = [ + 'screenshotLight' => [ + 'headers' => [ 'x-appwrite-hostname' => $rule->getAttribute('domain') ], + 'url' => 'http://appwrite/?appwrite-preview=1&appwrite-theme=light', + 'theme' => 'light' + ], + 'screenshotDark' => [ + 'headers' => [ 'x-appwrite-hostname' => $rule->getAttribute('domain') ], + 'url' => 'http://appwrite/?appwrite-preview=1&appwrite-theme=dark', + 'theme' => 'dark' + ], + ]; + + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 0); + $apiKey = $jwtObj->encode([ + 'hostnameOverride' => true, + 'disabledMetrics' => [ + METRIC_EXECUTIONS, + METRIC_EXECUTIONS_COMPUTE, + METRIC_EXECUTIONS_MB_SECONDS, + METRIC_NETWORK_REQUESTS, + METRIC_NETWORK_INBOUND, + METRIC_NETWORK_OUTBOUND, + 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), + ], + 'bannerDisabled' => true, + 'projectCheckDisabled' => true, + 'previewAuthDisabled' => true, + 'deploymentStatusIgnored' => true + ]); + + $screenshotError = null; + $screenshots = batch(\array_map(function ($key) use ($configs, $apiKey, $resource, $client, &$screenshotError) { + return function () use ($key, $configs, $apiKey, $resource, $client, &$screenshotError) { + try { + $config = $configs[$key]; + + $config['headers'] = \array_merge($config['headers'] ?? [], [ + 'x-appwrite-key' => API_KEY_DYNAMIC . '_' . $apiKey + ]); + $config['sleep'] = 3000; + + $frameworks = Config::getParam('frameworks', []); + $framework = $frameworks[$resource->getAttribute('framework', '')] ?? null; + if (!is_null($framework)) { + $config['sleep'] = $framework['screenshotSleep']; + } + + $fetchResponse = $client->fetch( + url: 'http://appwrite-browser:3000/v1/screenshots', + method: 'POST', + body: $config + ); + + if ($fetchResponse->getStatusCode() >= 400) { + throw new \Exception($fetchResponse->getBody()); + } + + $screenshot = $fetchResponse->getBody(); + + return ['key' => $key, 'screenshot' => $screenshot]; + } catch (\Throwable $th) { + $screenshotError = $th->getMessage(); + return; + } + }; + }, \array_keys($configs))); + + if (!\is_null($screenshotError)) { + throw new \Exception($screenshotError); + } + + foreach ($screenshots as $data) { + $key = $data['key']; + $screenshot = $data['screenshot']; + + $fileId = ID::unique(); + $fileName = $fileId . '.png'; + $path = $deviceForFiles->getPath($fileName); + $path = str_ireplace($deviceForFiles->getRoot(), $deviceForFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root + $success = $deviceForFiles->write($path, $screenshot, "image/png"); + + if (!$success) { + throw new \Exception("Screenshot failed to save"); + } + + $teamId = $project->getAttribute('teamId', ''); + $file = new Document([ + '$id' => $fileId, + '$permissions' => [ + Permission::read(Role::team(ID::custom($teamId))), + ], + 'bucketId' => $bucket->getId(), + 'bucketInternalId' => $bucket->getInternalId(), + 'name' => $fileName, + 'path' => $path, + 'signature' => $deviceForFiles->getFileHash($path), + 'mimeType' => $deviceForFiles->getFileMimeType($path), + 'sizeOriginal' => \strlen($screenshot), + 'sizeActual' => $deviceForFiles->getFileSize($path), + 'algorithm' => Compression::GZIP, + 'comment' => '', + 'chunksTotal' => 1, + 'chunksUploaded' => 1, + 'openSSLVersion' => null, + 'openSSLCipher' => null, + 'openSSLTag' => null, + 'openSSLIV' => null, + 'search' => implode(' ', [$fileId, $fileName]), + 'metadata' => ['content_type' => $deviceForFiles->getFileMimeType($path)], + ]); + + Authorization::skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getInternalId(), $file)); + + $deployment->setAttribute($key, $fileId); + } + + $logs = $deployment->getAttribute('buildLogs', ''); + $date = \date('H:i:s'); + $logs .= "[$date] [appwrite] Screenshot capturing finished. \n"; + + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + } catch (\Throwable $th) { + Console::warning("Screenshot failed to generate:"); + Console::warning($th->getMessage()); + Console::warning($th->getTraceAsString()); + + $logs = $deployment->getAttribute('buildLogs', ''); + $date = \date('H:i:s'); + $logs .= "[$date] [appwrite] Screenshot capturing failed. Deployment will continue. \n"; + + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); + } + } + + $logs = $deployment->getAttribute('buildLogs', ''); + $date = \date('H:i:s'); + $logs .= "[$date] [appwrite] Deployment finished. \n"; + $deployment->setAttribute('buildLogs', $logs); + + /** Update the status */ + $deployment->setAttribute('status', 'ready'); + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); + + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); + } + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + + if ($isVcsEnabled) { + $this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform); + } + + Console::success("Build id: $deploymentId created"); + + /** Set auto deploy */ + if ($deployment->getAttribute('activate') === true) { + $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()); + $resource = $dbForProject->updateDocument('functions', $resource->getId(), $resource); + + $queries = [ + Query::equal("projectInternalId", [$project->getInternalId()]), + Query::equal("type", ["deployment"]), + Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), + Query::equal('deploymentResourceType', ['function']), + Query::equal('trigger', ['manual']), + ]; + + 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; + $rule = $rule + ->setAttribute('deploymentId', $deployment->getId()) + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); + }); + break; + case 'sites': + $oldDeploymentInternalId = $resource->getAttribute('deploymentInternalId', ''); + + $resource->setAttribute('deploymentId', $deployment->getId()); + $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->getInternalId()]), + Query::equal("type", ["deployment"]), + Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), + Query::equal('deploymentResourceType', ['site']), + Query::equal('trigger', ['manual']), + ]; + + 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()) + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); + }); + + break; + } + } + + if ($resource->getCollection() === 'sites') { + // VCS branch + $branchName = $deployment->getAttribute('providerBranch'); + if (!empty($branchName)) { + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $domain = "branch-{$branchName}-{$resource->getId()}-{$project->getId()}.{$sitesDomain}"; + $ruleId = md5($domain); + + try { + $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + 'deploymentId' => $deployment->getId(), + 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentResourceType' => 'site', + 'deploymentResourceId' => $deployment->getId(), + 'deploymentResourceInternalId' => $deployment->getInternalId(), + 'deploymentVcsProviderBranch' => $branchName, + 'status' => 'verified', + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain]), + 'owner' => 'Appwrite', + 'region' => $project->getAttribute('region') + ])); + } catch (Duplicate $err) { + $rule = $dbForPlatform->getDocument('rules', $ruleId); + $rule = $rule + ->setAttribute('deploymentId', $deployment->getId()) + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); + } + + $this->listRules($project, [ + 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) { + $rule = $rule + ->setAttribute('deploymentId', $deployment->getId()) + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); + }); + } + } + + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { + Console::info('Build has been canceled'); + return; + } + + /** Update function schedule */ + + // Inform scheduler if function is still active + if ($resource->getCollection() === 'functions') { + $schedule = $dbForPlatform->getDocument('schedules', $resource->getAttribute('scheduleId')); + $schedule + ->setAttribute('resourceUpdatedAt', DateTime::now()) + ->setAttribute('schedule', $resource->getAttribute('schedule')) + ->setAttribute('active', !empty($resource->getAttribute('schedule')) && !empty($resource->getAttribute('deploymentId'))); + Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); + } + } catch (\Throwable $th) { + Console::warning('Build failed:'); + Console::error($th->getMessage()); + Console::error($th->getFile()); + Console::error($th->getLine()); + Console::error($th->getTraceAsString()); + + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { + Console::info('Build has been canceled'); + return; + } + + // Color message red + $message = $th->getMessage(); + if (!\str_contains($message, '')) { + $message = "" . $message; + } + + $endTime = DateTime::now(); + $durationEnd = \microtime(true); + $deployment->setAttribute('buildEndAt', $endTime); + $deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart))); + $deployment->setAttribute('status', 'failed'); + $deployment->setAttribute('buildLogs', $message); + + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); + + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); + } + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + + if ($isVcsEnabled) { + $this->runGitAction('failed', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform); + } + } finally { + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + + $this->sendUsage( + resource:$resource, + deployment: $deployment, + project: $project, + queue: $queueForStatsUsage + ); + } + } + + protected function sendUsage(Document $resource, Document $deployment, Document $project, StatsUsage $queue): void + { + switch ($deployment->getAttribute('status')) { + case 'ready': + $queue + ->addMetric(METRIC_BUILDS_SUCCESS, 1) // per project + ->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); + break; + case 'failed': + $queue + ->addMetric(METRIC_BUILDS_FAILED, 1) // per project + ->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); + break; + } + + $queue + ->addMetric(METRIC_BUILDS, 1) // per project + ->addMetric(METRIC_BUILDS_STORAGE, $deployment->getAttribute('buildSize', 0)) + ->addMetric(METRIC_BUILDS_COMPUTE, (int)$deployment->getAttribute('buildDuration', 0) * 1000) + ->addMetric(METRIC_BUILDS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS), 1) // per function + ->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))) + ->setProject($project) + ->trigger(); + } + + protected function getRuntime(Document $resource, string $version): array + { + $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); + $key = $resource->getAttribute('runtime'); + $runtime = match ($resource->getCollection()) { + 'functions' => $runtimes[$resource->getAttribute('runtime')] ?? null, + 'sites' => $runtimes[$resource->getAttribute('buildRuntime')] ?? null, + default => null + }; + if (\is_null($runtime)) { + throw new \Exception('Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported'); + } + + return $runtime; + } + + protected function getVersion(Document $resource): string + { + return match ($resource->getCollection()) { + 'functions' => $resource->getAttribute('version', 'v2'), + 'sites' => 'v5', + }; + } + + protected function getCommand(Document $resource, Document $deployment): string + { + if ($resource->getCollection() === 'functions') { + return $deployment->getAttribute('buildCommands', ''); + } elseif ($resource->getCollection() === 'sites') { + $commands = []; + + $frameworks = Config::getParam('frameworks', []); + $framework = $frameworks[$resource->getAttribute('framework', '')] ?? null; + + $envCommand = ''; + $bundleCommand = ''; + if (!is_null($framework)) { + $envCommand = $framework['envCommand'] ?? ''; + $bundleCommand = $framework['bundleCommand'] ?? ''; + } + + $commands[] = $envCommand; + $commands[] = $deployment->getAttribute('buildCommands', ''); + $commands[] = $bundleCommand; + + $commands = array_filter($commands, fn ($command) => !empty($command)); + + return implode(' && ', $commands); + } + + return ''; + } + + /** + * @param string $status + * @param GitHub $github + * @param string $providerCommitHash + * @param string $owner + * @param string $repositoryName + * @param Document $project + * @param Document $resource + * @param string $deploymentId + * @param Database $dbForProject + * @param Database $dbForPlatform + * @return void + * @throws Structure + * @throws \Utopia\Database\Exception + * @throws Authorization + * @throws Conflict + * @throws Restricted + */ + protected function runGitAction( + string $status, + GitHub $github, + string $providerCommitHash, + string $owner, + string $repositoryName, + Document $project, + Document $resource, + string $deploymentId, + Database $dbForProject, + Database $dbForPlatform + ): void { + if ($resource->getAttribute('providerSilentMode', false) === true) { + return; + } + + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + $commentId = $deployment->getAttribute('providerCommentId', ''); + + if (!empty($providerCommitHash)) { + $message = match ($status) { + 'ready' => 'Build succeeded.', + 'failed' => 'Build failed.', + 'processing' => 'Building...', + default => $status + }; + + $state = match ($status) { + 'ready' => 'success', + 'failed' => 'failure', + 'processing' => 'pending', + default => $status + }; + + $resourceName = $resource->getAttribute('name'); + $projectName = $project->getAttribute('name'); + + $name = "{$resourceName} ({$projectName})"; + + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $hostname = System::getEnv('_APP_DOMAIN'); + + $projectId = $project->getId(); + $resourceId = $resource->getId(); + $providerTargetUrl = match ($resource->getCollection()) { + 'functions' => "{$protocol}://{$hostname}/console/project-{$projectId}/functions/function-{$resourceId}", + 'sites' => "{$protocol}://{$hostname}/console/project-{$projectId}/sites/site-{$resourceId}", + default => throw new \Exception('Invalid resource type') + }; + + $github->updateCommitStatus($repositoryName, $providerCommitHash, $owner, $state, $message, $providerTargetUrl, $name); + } + + if (!empty($commentId)) { + $retries = 0; + + while (true) { + $retries++; + + try { + $dbForPlatform->createDocument('vcsCommentLocks', new Document([ + '$id' => $commentId + ])); + break; + } catch (\Throwable $err) { + if ($retries >= 9) { + throw $err; + } + + \sleep(1); + } + } + + // Wrap in try/finally to ensure lock file gets deleted + try { + $resourceType = match($resource->getCollection()) { + 'functions' => 'function', + 'sites' => 'site', + default => throw new \Exception('Invalid resource type') + }; + + $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ + Query::equal("projectInternalId", [$project->getInternalId()]), + Query::equal("type", ["deployment"]), + Query::equal("deploymentInternalId", [$deployment->getInternalId()]), + ])); + + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $previewUrl = match($resource->getCollection()) { + 'functions' => '', + 'sites' => !empty($rule) ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : '', + default => throw new \Exception('Invalid resource type') + }; + + $comment = new Comment(); + $comment->parseComment($github->getComment($owner, $repositoryName, $commentId)); + $comment->addBuild($project, $resource, $resourceType, $status, $deployment->getId(), ['type' => 'logs'], $previewUrl); + $github->updateComment($owner, $repositoryName, $commentId, $comment->generateComment()); + } finally { + $dbForPlatform->deleteDocument('vcsCommentLocks', $commentId); + } + } + } + + 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/Proxy/Http/Rules/API/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php new file mode 100644 index 0000000000..b6349c3aea --- /dev/null +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php @@ -0,0 +1,171 @@ +<?php + +namespace Appwrite\Platform\Modules\Proxy\Http\Rules\API; + +use Appwrite\Event\Certificate; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Network\Validator\DNS; +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\Exception\Duplicate; +use Utopia\Database\Helpers\ID; +use Utopia\Domains\Domain; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\System\System; +use Utopia\Validator\AnyOf; +use Utopia\Validator\Domain as ValidatorDomain; +use Utopia\Validator\IP; + +class Create extends Action +{ + use HTTP; + + public static function getName() + { + return 'createAPIRule'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/proxy/rules/api') + ->groups(['api', 'proxy']) + ->desc('Create API rule') + ->label('scope', 'rules.write') + ->label('event', 'rules.[ruleId].create') + ->label('audits.event', 'rule.create') + ->label('audits.resource', 'rule/{response.$id}') + ->label('sdk', new Method( + namespace: 'proxy', + name: 'createAPIRule', + description: <<<EOT + Create a new proxy rule for serving Appwrite's API on custom domain. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROXY_RULE, + ) + ] + )) + ->label('abuse-limit', 10) + ->label('abuse-key', 'userId:{userId}, url:{url}') + ->label('abuse-time', 60) + ->param('domain', null, new ValidatorDomain(), 'Domain name.') + ->inject('response') + ->inject('project') + ->inject('queueForCertificates') + ->inject('queueForEvents') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action(string $domain, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform) + { + $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + + $deniedDomains = [ + $mainDomain, + $sitesDomain, + $functionsDomain, + 'localhost', + APP_HOSTNAME_INTERNAL, + ]; + + if (\in_array($domain, $deniedDomains)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.'); + } + + if (\str_starts_with($domain, 'commit-') || \str_starts_with($domain, 'branch-')) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.'); + } + + try { + $domain = new Domain($domain); + } catch (\Throwable) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); + } + + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique(); + + $status = 'created'; + if (\str_ends_with($domain->get(), $functionsDomain) || \str_ends_with($domain->get(), $sitesDomain)) { + $status = 'verified'; + } + if ($status === 'created') { + $validators = []; + $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')); + 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); + } + if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) { + $validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA); + } + + if (empty($validators)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.'); + } + + $validator = new AnyOf($validators, AnyOf::TYPE_STRING); + if ($validator->isValid($domain->get())) { + $status = 'verifying'; + } + } + + $owner = ''; + if ( + ($functionsDomain != '' && \str_ends_with($domain->get(), $functionsDomain)) || + ($sitesDomain != '' && \str_ends_with($domain->get(), $sitesDomain)) + ) { + $owner = 'Appwrite'; + } + + $rule = new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain->get(), + 'status' => $status, + 'type' => 'api', + 'trigger' => 'manual', + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain->get()]), + 'owner' => $owner, + 'region' => $project->getAttribute('region') + ]); + + try { + $rule = $dbForPlatform->createDocument('rules', $rule); + } catch (Duplicate $e) { + throw new Exception(Exception::RULE_ALREADY_EXISTS); + } + + if ($rule->getAttribute('status', '') === 'verifying') { + $queueForCertificates + ->setDomain(new Document([ + 'domain' => $rule->getAttribute('domain') + ])) + ->trigger(); + } + + $queueForEvents->setParam('ruleId', $rule->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($rule, Response::MODEL_PROXY_RULE); + } +} diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php new file mode 100644 index 0000000000..a85a4fa063 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php @@ -0,0 +1,185 @@ +<?php + +namespace Appwrite\Platform\Modules\Proxy\Http\Rules\Function; + +use Appwrite\Event\Certificate; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Network\Validator\DNS; +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\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; +use Utopia\System\System; +use Utopia\Validator\AnyOf; +use Utopia\Validator\Domain as ValidatorDomain; +use Utopia\Validator\IP; +use Utopia\Validator\Text; + +class Create extends Action +{ + use HTTP; + + public static function getName() + { + return 'createFunctionRule'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/proxy/rules/function') + ->groups(['api', 'proxy']) + ->desc('Create function rule') + ->label('scope', 'rules.write') + ->label('event', 'rules.[ruleId].create') + ->label('audits.event', 'rule.create') + ->label('audits.resource', 'rule/{response.$id}') + ->label('sdk', new Method( + namespace: 'proxy', + name: 'createFunctionRule', + description: <<<EOT + Create a new proxy rule for executing Appwrite Function on custom domain. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROXY_RULE, + ) + ] + )) + ->label('abuse-limit', 10) + ->label('abuse-key', 'userId:{userId}, url:{url}') + ->label('abuse-time', 60) + ->param('domain', null, new ValidatorDomain(), 'Domain name.') + ->param('functionId', '', new UID(), 'ID of function to be executed.') + ->param('branch', '', new Text(255, 0), 'Name of VCS branch to deploy changes automatically', true) + ->inject('response') + ->inject('project') + ->inject('queueForCertificates') + ->inject('queueForEvents') + ->inject('dbForPlatform') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $domain, string $functionId, string $branch, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject) + { + $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + + $deniedDomains = [ + $mainDomain, + $sitesDomain, + $functionsDomain, + 'localhost', + APP_HOSTNAME_INTERNAL, + ]; + + if (\in_array($domain, $deniedDomains)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.'); + } + + try { + $domain = new Domain($domain); + } catch (\Throwable) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); + } + + $function = $dbForProject->getDocument('functions', $functionId); + if ($function->isEmpty()) { + throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND); + } + + $deployment = $dbForProject->getDocument('deployments', $function->getAttribute('deploymentId', '')); + + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique(); + + $status = 'created'; + if (\str_ends_with($domain->get(), $functionsDomain) || \str_ends_with($domain->get(), $sitesDomain)) { + $status = 'verified'; + } + if ($status === 'created') { + $validators = []; + $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')); + 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); + } + if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) { + $validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA); + } + + if (empty($validators)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.'); + } + + $validator = new AnyOf($validators, AnyOf::TYPE_STRING); + if ($validator->isValid($domain->get())) { + $status = 'verifying'; + } + } + + $owner = ''; + if ( + ($functionsDomain != '' && \str_ends_with($domain->get(), $functionsDomain)) || + ($sitesDomain != '' && \str_ends_with($domain->get(), $sitesDomain)) + ) { + $owner = 'Appwrite'; + } + + $rule = new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain->get(), + 'status' => $status, + 'type' => 'deployment', + 'trigger' => 'manual', + 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), + 'deploymentResourceType' => 'function', + 'deploymentResourceId' => $function->getId(), + 'deploymentResourceInternalId' => $function->getInternalId(), + 'deploymentVcsProviderBranch' => $branch, + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain->get(), $branch]), + 'owner' => $owner, + 'region' => $project->getAttribute('region') + ]); + + try { + $rule = $dbForPlatform->createDocument('rules', $rule); + } catch (Duplicate $e) { + throw new Exception(Exception::RULE_ALREADY_EXISTS); + } + + if ($rule->getAttribute('status', '') === 'verifying') { + $queueForCertificates + ->setDomain(new Document([ + 'domain' => $rule->getAttribute('domain') + ])) + ->trigger(); + } + + $queueForEvents->setParam('ruleId', $rule->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($rule, Response::MODEL_PROXY_RULE); + } +} diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php new file mode 100644 index 0000000000..58271ef08e --- /dev/null +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -0,0 +1,173 @@ +<?php + +namespace Appwrite\Platform\Modules\Proxy\Http\Rules\Redirect; + +use Appwrite\Event\Certificate; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Network\Validator\DNS; +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\Exception\Duplicate; +use Utopia\Database\Helpers\ID; +use Utopia\Domains\Domain; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\System\System; +use Utopia\Validator\AnyOf; +use Utopia\Validator\Domain as ValidatorDomain; +use Utopia\Validator\IP; +use Utopia\Validator\URL; +use Utopia\Validator\WhiteList; + +class Create extends Action +{ + use HTTP; + + public static function getName() + { + return 'createRedirectRule'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/proxy/rules/redirect') + ->groups(['api', 'proxy']) + ->desc('Create Redirect rule') + ->label('scope', 'rules.write') + ->label('event', 'rules.[ruleId].create') + ->label('audits.event', 'rule.create') + ->label('audits.resource', 'rule/{response.$id}') + ->label('sdk', new Method( + namespace: 'proxy', + name: 'createRedirectRule', + description: <<<EOT + Create a new proxy rule for to redirect from custom domain to another domain. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROXY_RULE, + ) + ] + )) + ->label('abuse-limit', 10) + ->label('abuse-key', 'userId:{userId}, url:{url}') + ->label('abuse-time', 60) + ->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') + ->inject('response') + ->inject('project') + ->inject('queueForCertificates') + ->inject('queueForEvents') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action(string $domain, string $url, int $statusCode, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform) + { + $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + + $deniedDomains = [ + $mainDomain, + $sitesDomain, + $functionsDomain, + 'localhost', + APP_HOSTNAME_INTERNAL, + ]; + + if (\in_array($domain, $deniedDomains)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.'); + } + + try { + $domain = new Domain($domain); + } catch (\Throwable) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); + } + + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique(); + + $status = 'created'; + if (\str_ends_with($domain->get(), $functionsDomain) || \str_ends_with($domain->get(), $sitesDomain)) { + $status = 'verified'; + } + if ($status === 'created') { + $validators = []; + $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')); + 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); + } + if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) { + $validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA); + } + + if (empty($validators)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.'); + } + + $validator = new AnyOf($validators, AnyOf::TYPE_STRING); + if ($validator->isValid($domain->get())) { + $status = 'verifying'; + } + } + + $owner = ''; + if ( + ($functionsDomain != '' && \str_ends_with($domain->get(), $functionsDomain)) || + ($sitesDomain != '' && \str_ends_with($domain->get(), $sitesDomain)) + ) { + $owner = 'Appwrite'; + } + + $rule = new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain->get(), + 'status' => $status, + 'type' => 'redirect', + 'trigger' => 'manual', + 'redirectUrl' => $url, + 'redirectStatusCode' => $statusCode, + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain->get()]), + 'owner' => $owner, + 'region' => $project->getAttribute('region') + ]); + + try { + $rule = $dbForPlatform->createDocument('rules', $rule); + } catch (Duplicate $e) { + throw new Exception(Exception::RULE_ALREADY_EXISTS); + } + + if ($rule->getAttribute('status', '') === 'verifying') { + $queueForCertificates + ->setDomain(new Document([ + 'domain' => $rule->getAttribute('domain') + ])) + ->trigger(); + } + + $queueForEvents->setParam('ruleId', $rule->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($rule, Response::MODEL_PROXY_RULE); + } +} diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php new file mode 100644 index 0000000000..1a0cbe7fdc --- /dev/null +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php @@ -0,0 +1,185 @@ +<?php + +namespace Appwrite\Platform\Modules\Proxy\Http\Rules\Site; + +use Appwrite\Event\Certificate; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Network\Validator\DNS; +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\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; +use Utopia\System\System; +use Utopia\Validator\AnyOf; +use Utopia\Validator\Domain as ValidatorDomain; +use Utopia\Validator\IP; +use Utopia\Validator\Text; + +class Create extends Action +{ + use HTTP; + + public static function getName() + { + return 'createSiteRule'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/proxy/rules/site') + ->groups(['api', 'proxy']) + ->desc('Create site rule') + ->label('scope', 'rules.write') + ->label('event', 'rules.[ruleId].create') + ->label('audits.event', 'rule.create') + ->label('audits.resource', 'rule/{response.$id}') + ->label('sdk', new Method( + namespace: 'proxy', + name: 'createSiteRule', + description: <<<EOT + Create a new proxy rule for serving Appwrite Site on custom domain. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_PROXY_RULE, + ) + ] + )) + ->label('abuse-limit', 10) + ->label('abuse-key', 'userId:{userId}, url:{url}') + ->label('abuse-time', 60) + ->param('domain', null, new ValidatorDomain(), 'Domain name.') + ->param('siteId', '', new UID(), 'ID of site to be executed.') + ->param('branch', '', new Text(255, 0), 'Name of VCS branch to deploy changes automatically', true) + ->inject('response') + ->inject('project') + ->inject('queueForCertificates') + ->inject('queueForEvents') + ->inject('dbForPlatform') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $domain, string $siteId, string $branch, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject) + { + $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + + $deniedDomains = [ + $mainDomain, + $sitesDomain, + $functionsDomain, + 'localhost', + APP_HOSTNAME_INTERNAL, + ]; + + if (\in_array($domain, $deniedDomains)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'This domain name is not allowed. Please pick another one.'); + } + + try { + $domain = new Domain($domain); + } catch (\Throwable) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); + } + + $site = $dbForProject->getDocument('sites', $siteId); + if ($site->isEmpty()) { + throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND); + } + + $deployment = $dbForProject->getDocument('deployments', $site->getAttribute('deploymentId', '')); + + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique(); + + $status = 'created'; + if (\str_ends_with($domain->get(), $functionsDomain) || \str_ends_with($domain->get(), $sitesDomain)) { + $status = 'verified'; + } + if ($status === 'created') { + $validators = []; + $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')); + 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); + } + if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) { + $validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA); + } + + if (empty($validators)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'At least one of domain targets environment variable must be configured.'); + } + + $validator = new AnyOf($validators, AnyOf::TYPE_STRING); + if ($validator->isValid($domain->get())) { + $status = 'verifying'; + } + } + + $owner = ''; + if ( + ($functionsDomain != '' && \str_ends_with($domain->get(), $functionsDomain)) || + ($sitesDomain != '' && \str_ends_with($domain->get(), $sitesDomain)) + ) { + $owner = 'Appwrite'; + } + + $rule = new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain->get(), + 'status' => $status, + 'type' => 'deployment', + 'trigger' => 'manual', + 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), + 'deploymentResourceType' => 'site', + 'deploymentResourceId' => $site->getId(), + 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentVcsProviderBranch' => $branch, + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain->get(), $branch]), + 'owner' => $owner, + 'region' => $project->getAttribute('region') + ]); + + try { + $rule = $dbForPlatform->createDocument('rules', $rule); + } catch (Duplicate $e) { + throw new Exception(Exception::RULE_ALREADY_EXISTS); + } + + if ($rule->getAttribute('status', '') === 'verifying') { + $queueForCertificates + ->setDomain(new Document([ + 'domain' => $rule->getAttribute('domain') + ])) + ->trigger(); + } + + $queueForEvents->setParam('ruleId', $rule->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($rule, Response::MODEL_PROXY_RULE); + } +} diff --git a/src/Appwrite/Platform/Modules/Proxy/Module.php b/src/Appwrite/Platform/Modules/Proxy/Module.php new file mode 100644 index 0000000000..cd8f6f86dc --- /dev/null +++ b/src/Appwrite/Platform/Modules/Proxy/Module.php @@ -0,0 +1,14 @@ +<?php + +namespace Appwrite\Platform\Modules\Proxy; + +use Appwrite\Platform\Modules\Proxy\Services\Http; +use Utopia\Platform; + +class Module extends Platform\Module +{ + public function __construct() + { + $this->addService('http', new Http()); + } +} diff --git a/src/Appwrite/Platform/Modules/Proxy/Services/Http.php b/src/Appwrite/Platform/Modules/Proxy/Services/Http.php new file mode 100644 index 0000000000..c5f11ad5be --- /dev/null +++ b/src/Appwrite/Platform/Modules/Proxy/Services/Http.php @@ -0,0 +1,23 @@ +<?php + +namespace Appwrite\Platform\Modules\Proxy\Services; + +use Appwrite\Platform\Modules\Proxy\Http\Rules\API\Create as CreateAPIRule; +use Appwrite\Platform\Modules\Proxy\Http\Rules\Function\Create as CreateFunctionRule; +use Appwrite\Platform\Modules\Proxy\Http\Rules\Redirect\Create as CreateRedirectRule; +use Appwrite\Platform\Modules\Proxy\Http\Rules\Site\Create as CreateSiteRule; +use Utopia\Platform\Service; + +class Http extends Service +{ + public function __construct() + { + $this->type = Service::TYPE_HTTP; + + // Rules + $this->addAction(CreateAPIRule::getName(), new CreateAPIRule()); + $this->addAction(CreateSiteRule::getName(), new CreateSiteRule()); + $this->addAction(CreateFunctionRule::getName(), new CreateFunctionRule()); + $this->addAction(CreateRedirectRule::getName(), new CreateRedirectRule()); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php new file mode 100644 index 0000000000..0b45c42e4b --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -0,0 +1,363 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Deployments; + +use Appwrite\Event\Build; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Storage\Device; +use Utopia\Storage\Validator\File; +use Utopia\Storage\Validator\FileExt; +use Utopia\Storage\Validator\FileSize; +use Utopia\Storage\Validator\Upload; +use Utopia\Swoole\Request; +use Utopia\System\System; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; + +class Create extends Action +{ + use HTTP; + + public static function getName() + { + return 'createDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/sites/:siteId/deployments') + ->desc('Create deployment') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('event', 'sites.[siteId].deployments.[deploymentId].create') + ->label('audits.event', 'deployment.create') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'createDeployment', + description: <<<EOT + 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. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_DEPLOYMENT, + ) + ], + requestType: 'multipart/form-data', + type: MethodType::UPLOAD, + packaging: true, + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('installCommand', null, new Text(8192, 0), 'Install Commands.', true) + ->param('buildCommand', null, new Text(8192, 0), 'Build Commands.', true) + ->param('outputDirectory', null, new Text(8192, 0), 'Output Directory.', true) + ->param('code', [], new File(), '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.', skipValidation: true) + ->param('activate', false, new Boolean(true), 'Automatically activate the deployment when it is finished building.') + ->inject('request') + ->inject('response') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->inject('project') + ->inject('queueForEvents') + ->inject('deviceForSites') + ->inject('deviceForLocal') + ->inject('queueForBuilds') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + ?string $installCommand, + ?string $buildCommand, + ?string $outputDirectory, + mixed $code, + mixed $activate, + Request $request, + Response $response, + Database $dbForProject, + Database $dbForPlatform, + Document $project, + Event $queueForEvents, + Device $deviceForSites, + Device $deviceForLocal, + Build $queueForBuilds + ) { + $activate = \strval($activate) === 'true' || \strval($activate) === '1'; + + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + if ($installCommand === null) { + $installCommand = $site->getAttribute('installCommand', ''); + } + + if ($buildCommand === null) { + $buildCommand = $site->getAttribute('buildCommand', ''); + } + + if ($outputDirectory === null) { + $outputDirectory = $site->getAttribute('outputDirectory', ''); + } + + $file = $request->getFiles('code'); + + // GraphQL multipart spec adds files with index keys + if (empty($file)) { + $file = $request->getFiles(0); + } + + if (empty($file)) { + throw new Exception(Exception::STORAGE_FILE_EMPTY, 'No file sent'); + } + + $fileExt = new FileExt([FileExt::TYPE_GZIP]); + $fileSizeValidator = new FileSize(System::getEnv('_APP_COMPUTE_SIZE_LIMIT', '30000000')); + $upload = new Upload(); + + // Make sure we handle a single file and multiple files the same way + $fileName = (\is_array($file['name']) && isset($file['name'][0])) ? $file['name'][0] : $file['name']; + $fileTmpName = (\is_array($file['tmp_name']) && isset($file['tmp_name'][0])) ? $file['tmp_name'][0] : $file['tmp_name']; + $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; + + if (!$fileExt->isValid($file['name'])) { // Check if file type is allowed + throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED); + } + + $contentRange = $request->getHeader('content-range'); + $deploymentId = ID::unique(); + $chunk = 1; + $chunks = 1; + + if (!empty($contentRange)) { + $start = $request->getContentRangeStart(); + $end = $request->getContentRangeEnd(); + $fileSize = $request->getContentRangeSize(); + $deploymentId = $request->getHeader('x-appwrite-id', $deploymentId); + // TODO make `end >= $fileSize` in next breaking version + if (is_null($start) || is_null($end) || is_null($fileSize) || $end > $fileSize) { + throw new Exception(Exception::STORAGE_INVALID_CONTENT_RANGE); + } + + // TODO remove the condition that checks `$end === $fileSize` in next breaking version + if ($end === $fileSize - 1 || $end === $fileSize) { + //if it's a last chunks the chunk size might differ, so we set the $chunks and $chunk to notify it's last chunk + $chunks = $chunk = -1; + } else { + // Calculate total number of chunks based on the chunk size i.e ($rangeEnd - $rangeStart) + $chunks = (int) ceil($fileSize / ($end + 1 - $start)); + $chunk = (int) ($start / ($end + 1 - $start)) + 1; + } + } + + if (!$fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit + throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE); + } + + if (!$upload->isValid($fileTmpName)) { + throw new Exception(Exception::STORAGE_INVALID_FILE); + } + + // Save to storage + $fileSize ??= $deviceForLocal->getFileSize($fileTmpName); + $path = $deviceForSites->getPath($deploymentId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + + $metadata = ['content_type' => $deviceForLocal->getFileMimeType($fileTmpName)]; + if (!$deployment->isEmpty()) { + $chunks = $deployment->getAttribute('sourceChunksTotal', 1); + $metadata = $deployment->getAttribute('sourceMetadata', []); + if ($chunk === -1) { + $chunk = $chunks; + } + } + + $chunksUploaded = $deviceForSites->upload($fileTmpName, $path, $chunk, $chunks, $metadata); + + if (empty($chunksUploaded)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed moving file'); + } + + $type = $request->getHeader('x-sdk-language') === 'cli' ? 'cli' : 'manual'; + + $commands = []; + if (!empty($installCommand)) { + $commands[] = $installCommand; + } + if (!empty($buildCommand)) { + $commands[] = $buildCommand; + } + + if ($chunksUploaded === $chunks) { + if ($activate) { + // Remove deploy for all other deployments. + $activeDeployments = $dbForProject->find('deployments', [ + Query::equal('activate', [true]), + Query::equal('resourceId', [$siteId]), + Query::equal('resourceType', ['sites']) + ]); + + foreach ($activeDeployments as $activeDeployment) { + $activeDeployment->setAttribute('activate', false); + $dbForProject->updateDocument('deployments', $activeDeployment->getId(), $activeDeployment); + } + } + + $fileSize = $deviceForSites->getFileSize($path); + + if ($deployment->isEmpty()) { + $deployment = $dbForProject->createDocument('deployments', new Document([ + '$id' => $deploymentId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'resourceInternalId' => $site->getInternalId(), + 'resourceId' => $site->getId(), + 'resourceType' => 'sites', + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $outputDirectory, + 'adapter' => $site->getAttribute('adapter', ''), + 'fallbackFile' => $site->getAttribute('fallbackFile', ''), + 'sourcePath' => $path, + 'sourceSize' => $fileSize, + 'totalSize' => $fileSize, + 'search' => implode(' ', [$deploymentId]), + 'activate' => $activate, + 'sourceMetadata' => $metadata, + 'type' => $type, + ])); + + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $domain = ID::unique() . "." . $sitesDomain; + + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); + + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + '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 { + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceSize', $fileSize)->setAttribute('sourceMetadata', $metadata)); + } + + // Start the build + $queueForBuilds + ->setType(BUILD_TYPE_DEPLOYMENT) + ->setResource($site) + ->setDeployment($deployment); + } else { + if ($deployment->isEmpty()) { + $deployment = $dbForProject->createDocument('deployments', new Document([ + '$id' => $deploymentId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'resourceInternalId' => $site->getInternalId(), + 'resourceId' => $site->getId(), + 'resourceType' => 'sites', + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $outputDirectory, + 'adapter' => $site->getAttribute('adapter', ''), + 'fallbackFile' => $site->getAttribute('fallbackFile', ''), + 'sourcePath' => $path, + 'sourceSize' => $fileSize, + 'totalSize' => $fileSize, + 'sourceChunksTotal' => $chunks, + 'sourceChunksUploaded' => $chunksUploaded, + 'search' => implode(' ', [$deploymentId]), + 'activate' => $activate, + 'sourceMetadata' => $metadata, + 'type' => $type, + ])); + + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $domain = ID::unique() . "." . $sitesDomain; + $ruleId = md5($domain); + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + 'value' => $deployment->getId(), + 'status' => 'verified', + 'certificateId' => '', + 'search' => implode(' ', [$ruleId, $domain]), + ])) + ); + } else { + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment->setAttribute('sourceChunksUploaded', $chunksUploaded)->setAttribute('sourceMetadata', $metadata)); + } + } + + $metadata = null; + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php new file mode 100644 index 0000000000..9d30b21a11 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php @@ -0,0 +1,137 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Deployments; + +use Appwrite\Event\Delete as DeleteEvent; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +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\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Storage\Device; + +class Delete extends Action +{ + use HTTP; + + public static function getName() + { + return 'deleteDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId') + ->desc('Delete deployment') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('event', 'sites.[siteId].deployments.[deploymentId].delete') + ->label('audits.event', 'deployment.delete') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'deleteDeployment', + description: <<<EOT + Delete a site deployment by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDeletes') + ->inject('queueForEvents') + ->inject('deviceForSites') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $deploymentId, + Response $response, + Database $dbForProject, + DeleteEvent $queueForDeletes, + Event $queueForEvents, + Device $deviceForSites + ) { + $site = $dbForProject->getDocument('sites', $siteId); + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if ($deployment->getAttribute('resourceId') !== $site->getId()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if (!$dbForProject->deleteDocument('deployments', $deployment->getId())) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from DB'); + } + + if (!empty($deployment->getAttribute('sourcePath', ''))) { + if (!($deviceForSites->delete($deployment->getAttribute('sourcePath', '')))) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from storage'); + } + } + + if ($site->getAttribute('latestDeploymentId') === $deployment->getId()) { + $latestDeployment = $dbForProject->findOne('deployments', [ + Query::equal('resourceType', ['sites']), + Query::equal('resourceInternalId', [$site->getInternalId()]), + Query::orderDesc('$createdAt'), + ]); + $site = $dbForProject->updateDocument( + 'sites', + $site->getId(), + $site + ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->isEmpty() ? '' : $latestDeployment->getCreatedAt()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getInternalId()) + ->setAttribute('latestDeploymentId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getId()) + ->setAttribute('latestDeploymentStatus', $latestDeployment->isEmpty() ? '' : $latestDeployment->getAttribute('status', '')) + ); + } + + if ($site->getAttribute('deploymentId') === $deployment->getId()) { // Reset site deployment + $site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [ + 'deploymentId' => '', + 'deploymentInternalId' => '', + 'deploymentScreenshotDark' => '', + 'deploymentScreenshotLight' => '', + 'deploymentCreatedAt' => '', + ]))); + } + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $queueForDeletes + ->setType(DELETE_TYPE_DOCUMENT) + ->setDocument($deployment); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php new file mode 100644 index 0000000000..77301a2aa1 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php @@ -0,0 +1,150 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Download; + +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\MethodType; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Storage\Device; +use Utopia\Swoole\Request; +use Utopia\Validator\WhiteList; + +class Get extends Action +{ + use HTTP; + + public static function getName() + { + return 'getDeploymentDownload'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId/download') + ->desc('Download deployment') + ->groups(['api', 'sites']) + ->label('scope', 'sites.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'getDeploymentDownload', + description: <<<EOT + 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. + EOT, + auth: [AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_NONE + ) + ], + type: MethodType::LOCATION, + contentType: ContentType::ANY, + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->param('type', 'source', new WhiteList(['source', 'output']), 'Deployment file to download. Can be: "source", "output".', true) + ->inject('response') + ->inject('request') + ->inject('dbForProject') + ->inject('deviceForSites') + ->inject('deviceForBuilds') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $deploymentId, + string $type, + Response $response, + Request $request, + Database $dbForProject, + Device $deviceForSites, + Device $deviceForBuilds + ) { + $site = $dbForProject->getDocument('sites', $siteId); + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if ($deployment->getAttribute('resourceId') !== $site->getId()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + switch ($type) { + case 'output': + $path = $deployment->getAttribute('buildPath', ''); + $device = $deviceForBuilds; + break; + case 'source': + $path = $deployment->getAttribute('sourcePath', ''); + $device = $deviceForSites; + break; + } + + if (!$device->exists($path)) { + throw new Exception(Exception::BUILD_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('X-Peak', \memory_get_peak_usage()) + ->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '-' . $type . '.tar.gz"'); + + $size = $device->getFileSize($path); + $rangeHeader = $request->getHeader('range'); + + if (!empty($rangeHeader)) { + $start = $request->getRangeStart(); + $end = $request->getRangeEnd(); + $unit = $request->getRangeUnit(); + + if ($end === null) { + $end = min(($start + MAX_OUTPUT_CHUNK_SIZE - 1), ($size - 1)); + } + + if ($unit !== 'bytes' || $start >= $end || $end >= $size) { + throw new Exception(Exception::STORAGE_INVALID_RANGE); + } + + $response + ->addHeader('Accept-Ranges', 'bytes') + ->addHeader('Content-Range', 'bytes ' . $start . '-' . $end . '/' . $size) + ->addHeader('Content-Length', $end - $start + 1) + ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); + + $response->send($device->read($path, $start, ($end - $start + 1))); + } + + if ($size > APP_STORAGE_READ_BUFFER) { + for ($i = 0; $i < ceil($size / MAX_OUTPUT_CHUNK_SIZE); $i++) { + $response->chunk( + $device->read( + $path, + ($i * MAX_OUTPUT_CHUNK_SIZE), + min(MAX_OUTPUT_CHUNK_SIZE, $size - ($i * MAX_OUTPUT_CHUNK_SIZE)) + ), + (($i + 1) * MAX_OUTPUT_CHUNK_SIZE) >= $size + ); + } + } else { + $response->send($device->read($path)); + } + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php new file mode 100644 index 0000000000..1b3b08b7e3 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -0,0 +1,179 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Duplicate; + +use Appwrite\Event\Build; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +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\Helpers\ID; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Storage\Device; +use Utopia\System\System; + +class Create extends Action +{ + use HTTP; + + public static function getName() + { + return 'createDuplicateDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/sites/:siteId/deployments/duplicate') + ->desc('Create duplicate deployment') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('event', 'sites.[siteId].deployments.[deploymentId].update') + ->label('audits.event', 'deployment.update') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'createDuplicateDeployment', + description: <<<EOT + 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. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_DEPLOYMENT, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->inject('response') + ->inject('project') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->inject('queueForEvents') + ->inject('queueForBuilds') + ->inject('deviceForSites') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $deploymentId, + Response $response, + Document $project, + Database $dbForProject, + Database $dbForPlatform, + Event $queueForEvents, + Build $queueForBuilds, + Device $deviceForSites + ) { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + $path = $deployment->getAttribute('sourcePath'); + if (empty($path) || !$deviceForSites->exists($path)) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + $deploymentId = ID::unique(); + + $destination = $deviceForSites->getPath($deploymentId . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); + $deviceForSites->transfer($path, $destination, $deviceForSites); + + $commands = []; + + if (!empty($site->getAttribute('installCommand', ''))) { + $commands[] = $site->getAttribute('installCommand', ''); + } + if (!empty($site->getAttribute('buildCommand', ''))) { + $commands[] = $site->getAttribute('buildCommand', ''); + } + + $deployment->removeAttribute('$internalId'); + $deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([ + '$internalId' => '', + '$id' => $deploymentId, + 'sourcePath' => $destination, + 'totalSize' => $deployment->getAttribute('sourceSize', 0), + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $site->getAttribute('outputDirectory', ''), + 'adapter' => $site->getAttribute('adapter', ''), + 'fallbackFile' => $site->getAttribute('fallbackFile', ''), + 'search' => implode(' ', [$deploymentId]), + 'screenshotLight' => '', + 'screenshotDark' => '', + 'buildStartAt' => null, + 'buildEndAt' => null, + 'buildDuration' => 0, + 'buildSize' => 0, + 'status' => 'waiting', + 'buildPath' => '', + 'buildLogs' => '', + ])); + + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + + // Preview deployments for sites + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $domain = ID::unique() . "." . $sitesDomain; + + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); + + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + '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') + ])) + ); + + $queueForBuilds + ->setType(BUILD_TYPE_DEPLOYMENT) + ->setResource($site) + ->setDeployment($deployment); + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php new file mode 100644 index 0000000000..68a5b2619a --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Get.php @@ -0,0 +1,74 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Deployments; + +use Appwrite\Extend\Exception; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Get extends Action +{ + use HTTP; + + public static function getName() + { + return 'getDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId') + ->desc('Get deployment') + ->groups(['api', 'sites']) + ->label('scope', 'sites.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'getDeployment', + description: <<<EOT + Get a site deployment by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DEPLOYMENT, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $siteId, string $deploymentId, Response $response, Database $dbForProject) + { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if ($deployment->getAttribute('resourceId') !== $site->getId()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + $response->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php new file mode 100644 index 0000000000..7aade4e7ff --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php @@ -0,0 +1,117 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Status; + +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Executor\Executor; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Update extends Action +{ + use HTTP; + + public static function getName() + { + return 'updateDeploymentStatus'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId/status') + ->desc('Update deployment status') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('audits.event', 'deployment.update') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'updateDeploymentStatus', + description: <<<EOT + 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. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DEPLOYMENT, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('project') + ->inject('queueForEvents') + ->inject('executor') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $deploymentId, + Response $response, + Database $dbForProject, + Document $project, + Event $queueForEvents, + Executor $executor + ) { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if (\in_array($deployment->getAttribute('status'), ['ready', 'failed'])) { + throw new Exception(Exception::BUILD_ALREADY_COMPLETED); + } + + $startTime = new \DateTime($deployment->getAttribute('buildStartAt', 'now')); + $endTime = new \DateTime('now'); + $duration = $endTime->getTimestamp() - $startTime->getTimestamp(); + + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttributes([ + 'buildEndAt' => DateTime::now(), + 'buildDuration' => $duration, + 'status' => 'canceled' + ])); + + if ($deployment->getInternalId() === $site->getAttribute('latestDeploymentInternalId', '')) { + $site = $site->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + } + + try { + $executor->deleteRuntime($project->getId(), $deploymentId . "-build"); + } catch (\Throwable $th) { + // Don't throw if the deployment doesn't exist + if ($th->getCode() !== 404) { + throw $th; + } + } + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php new file mode 100644 index 0000000000..f70455c466 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -0,0 +1,214 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Template; + +use Appwrite\Event\Build; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\Authorization; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Swoole\Request; +use Utopia\System\System; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; +use Utopia\VCS\Adapter\Git\GitHub; + +class Create extends Base +{ + use HTTP; + + public static function getName() + { + return 'createTemplateDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/sites/:siteId/deployments/template') + ->desc('Create template deployment') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('event', 'sites.[siteId].deployments.[deploymentId].create') + ->label('audits.event', 'deployment.create') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'createTemplateDeployment', + description: <<<EOT + Create a deployment based on a template. + + Use this endpoint with combination of [listTemplates](https://appwrite.io/docs/server/sites#listTemplates) to find the template details. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_DEPLOYMENT, + ) + ], + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('repository', '', new Text(128, 0), 'Repository name of the template.') + ->param('owner', '', new Text(128, 0), 'The name of the owner of the template.') + ->param('rootDirectory', '', new Text(128, 0), 'Path to site code in the template repo.') + ->param('version', '', new Text(128, 0), 'Version (tag) for the repo linked to the site template.') + ->param('activate', false, new Boolean(), 'Automatically activate the deployment when it is finished building.', true) + ->inject('request') + ->inject('response') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->inject('project') + ->inject('queueForEvents') + ->inject('queueForBuilds') + ->inject('gitHub') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $repository, + string $owner, + string $rootDirectory, + string $version, + bool $activate, + Request $request, + Response $response, + Database $dbForProject, + Database $dbForPlatform, + Document $project, + Event $queueForEvents, + Build $queueForBuilds, + GitHub $github + ) { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $template = new Document([ + 'repositoryName' => $repository, + 'ownerName' => $owner, + 'rootDirectory' => $rootDirectory, + 'version' => $version + ]); + + if (!empty($site->getAttribute('providerRepositoryId'))) { + $installation = $dbForPlatform->getDocument('installations', $site->getAttribute('installationId')); + + $deployment = $this->redeployVcsSite( + request: $request, + site: $site, + project: $project, + installation: $installation, + dbForProject: $dbForProject, + dbForPlatform: $dbForPlatform, + queueForBuilds: $queueForBuilds, + template: $template, + github: $github, + activate: $activate, + ); + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + + return; + } + + $commands = []; + if (!empty($site->getAttribute('installCommand', ''))) { + $commands[] = $site->getAttribute('installCommand', ''); + } + if (!empty($site->getAttribute('buildCommand', ''))) { + $commands[] = $site->getAttribute('buildCommand', ''); + } + + $deploymentId = ID::unique(); + $deployment = $dbForProject->createDocument('deployments', new Document([ + '$id' => $deploymentId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'resourceId' => $site->getId(), + 'resourceInternalId' => $site->getInternalId(), + 'resourceType' => 'sites', + 'buildCommands' => \implode(' && ', $commands), + 'buildOutput' => $site->getAttribute('outputDirectory', ''), + 'adapter' => $site->getAttribute('adapter', ''), + 'fallbackFile' => $site->getAttribute('fallbackFile', ''), + 'type' => 'manual', + 'search' => implode(' ', [$deploymentId]), + 'activate' => $activate, + ])); + + $site = $site + ->setAttribute('latestDeploymentId', $deployment->getId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); + $dbForProject->updateDocument('sites', $site->getId(), $site); + + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $domain = ID::unique() . "." . $sitesDomain; + + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain) : ID::unique(); + + Authorization::skip( + fn () => $dbForPlatform->createDocument('rules', new Document([ + '$id' => $ruleId, + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'domain' => $domain, + 'type' => 'deployment', + 'trigger' => 'deployment', + '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') + ])) + ); + + $queueForBuilds + ->setType(BUILD_TYPE_DEPLOYMENT) + ->setResource($site) + ->setDeployment($deployment) + ->setTemplate($template); + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php new file mode 100644 index 0000000000..b0585a27db --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Vcs/Create.php @@ -0,0 +1,124 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Vcs; + +use Appwrite\Event\Build; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Swoole\Request; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; +use Utopia\VCS\Adapter\Git\GitHub; + +class Create extends Base +{ + use HTTP; + + public static function getName() + { + return 'createVcsDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/sites/:siteId/deployments/vcs') + ->desc('Create VCS deployment') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('event', 'sites.[siteId].deployments.[deploymentId].create') + ->label('audits.event', 'deployment.create') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'createVcsDeployment', + description: <<<EOT + Create a deployment when a site is connected to VCS. + + This endpoint lets you create deployment from a branch, commit, or a tag. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_ACCEPTED, + model: Response::MODEL_DEPLOYMENT, + ) + ], + )) + ->param('siteId', '', new UID(), 'Site ID.') + // TODO: Support tag in future + ->param('type', '', new WhiteList(['branch', 'commit', 'tag']), 'Type of reference passed. Allowed values are: branch, commit') + ->param('reference', '', new Text(255), 'VCS reference to create deployment from. Depending on type this can be: branch name, commit hash') + ->param('activate', false, new Boolean(), 'Automatically activate the deployment when it is finished building.', true) + ->inject('request') + ->inject('response') + ->inject('dbForProject') + ->inject('dbForPlatform') + ->inject('project') + ->inject('queueForEvents') + ->inject('queueForBuilds') + ->inject('gitHub') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $type, + string $reference, + bool $activate, + Request $request, + Response $response, + Database $dbForProject, + Database $dbForPlatform, + Document $project, + Event $queueForEvents, + Build $queueForBuilds, + GitHub $github + ) { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $template = new Document(); + + $installation = $dbForPlatform->getDocument('installations', $site->getAttribute('installationId')); + + $deployment = $this->redeployVcsSite( + request: $request, + site: $site, + project: $project, + installation: $installation, + dbForProject: $dbForProject, + dbForPlatform: $dbForPlatform, + queueForBuilds: $queueForBuilds, + template: $template, + github: $github, + activate: $activate, + reference: $reference, + referenceType: $type + ); + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($deployment, Response::MODEL_DEPLOYMENT); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php new file mode 100644 index 0000000000..e041554132 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php @@ -0,0 +1,118 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Deployments; + +use Appwrite\Extend\Exception; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Database\Validator\Queries\Deployments; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Exception\Query as QueryException; +use Utopia\Database\Query; +use Utopia\Database\Validator\Query\Cursor; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Text; + +class XList extends Action +{ + use HTTP; + + public static function getName() + { + return 'listDeployments'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/:siteId/deployments') + ->desc('List deployments') + ->groups(['api', 'sites']) + ->label('scope', 'sites.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'listDeployments', + description: <<<EOT + Get a list of all the site's code deployments. You can use the query params to filter your results. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DEPLOYMENT_LIST, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('queries', [], new Deployments(), '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(', ', Deployments::ALLOWED_ATTRIBUTES), true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $siteId, array $queries, string $search, Response $response, Database $dbForProject) + { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + // Set resource queries + $queries[] = Query::equal('resourceInternalId', [$site->getInternalId()]); + $queries[] = Query::equal('resourceType', ['sites']); + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + if ($cursor) { + /** @var Query $cursor */ + + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $deploymentId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('deployments', $deploymentId); + + if ($cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Deployment '{$deploymentId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + + $results = $dbForProject->find('deployments', $queries); + $total = $dbForProject->count('deployments', $filterQueries, APP_LIMIT_COUNT); + + $response->dynamic(new Document([ + 'deployments' => $results, + 'total' => $total, + ]), Response::MODEL_DEPLOYMENT_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Frameworks/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Frameworks/XList.php new file mode 100644 index 0000000000..6317ef7514 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Frameworks/XList.php @@ -0,0 +1,66 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Frameworks; + +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +use Utopia\Database\Document; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listFrameworks'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/frameworks') + ->desc('List frameworks') + ->groups(['api']) + ->label('scope', 'public') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'listFrameworks', + description: <<<EOT + Get a list of all frameworks that are currently available on the server instance. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_FRAMEWORK_LIST, + ) + ] + )) + ->inject('response') + ->callback([$this, 'action']); + } + + public function action(Response $response) + { + $frameworks = Config::getParam('frameworks'); + + foreach ($frameworks as $key => $framework) { + if (!empty($framework['adapters'])) { + $frameworks[$key]['adapters'] = \array_values($framework['adapters']); + } + } + + $response->dynamic(new Document([ + 'total' => count($frameworks), + 'frameworks' => \array_values($frameworks) + ]), Response::MODEL_FRAMEWORK_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php new file mode 100644 index 0000000000..da13984adc --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php @@ -0,0 +1,88 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Logs; + +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Delete extends Base +{ + use HTTP; + + public static function getName() + { + return 'deleteLog'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/sites/:siteId/logs/:logId') + ->desc('Delete log') + ->groups(['api', 'sites']) + ->label('scope', 'log.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('event', 'sites.[siteId].logs.[logId].delete') + ->label('audits.event', 'logs.delete') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'deleteLog', + description: <<<EOT + Delete a site log by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('logId', '', new UID(), 'Log ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action(string $siteId, string $logId, Response $response, Database $dbForProject, Event $queueForEvents) + { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $log = $dbForProject->getDocument('executions', $logId); + if ($log->isEmpty()) { + throw new Exception(Exception::LOG_NOT_FOUND); + } + + if ($log->getAttribute('resourceType') !== 'sites' && $log->getAttribute('resourceInternalId') !== $site->getInternalId()) { + throw new Exception(Exception::LOG_NOT_FOUND); + } + + if (!$dbForProject->deleteDocument('executions', $log->getId())) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove log from DB'); + } + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('logId', $log->getId()) + ->setPayload($response->output($log, Response::MODEL_EXECUTION)); // TODO: Update model + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php new file mode 100644 index 0000000000..f640c164cc --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php @@ -0,0 +1,75 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Logs; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Get extends Base +{ + use HTTP; + + public static function getName() + { + return 'getLog'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/:siteId/logs/:logId') + ->desc('Get log') + ->groups(['api', 'sites']) + ->label('scope', 'log.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'getLog', + description: <<<EOT + Get a site request log by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EXECUTION, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('logId', '', new UID(), 'Log ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $siteId, string $logId, Response $response, Database $dbForProject) + { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty() || !$site->getAttribute('enabled')) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $log = $dbForProject->getDocument('executions', $logId); + + if ($log->getAttribute('resourceType') !== 'sites' && $log->getAttribute('resourceInternalId') !== $site->getInternalId()) { + throw new Exception(Exception::LOG_NOT_FOUND); + } + + if ($log->isEmpty()) { + throw new Exception(Exception::LOG_NOT_FOUND); + } + + $response->dynamic($log, Response::MODEL_EXECUTION); //TODO: Change to model log, but model log already exists - decide what to do + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php new file mode 100644 index 0000000000..8a9630b28b --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php @@ -0,0 +1,114 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Logs; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Database\Validator\Queries\Executions; +use Appwrite\Utopia\Database\Validator\Queries\Logs; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Exception\Query as QueryException; +use Utopia\Database\Query; +use Utopia\Database\Validator\Query\Cursor; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listLogs'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/:siteId/logs') + ->desc('List logs') + ->groups(['api', 'sites']) + ->label('scope', 'log.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'listLogs', + description: <<<EOT + Get a list of all site logs. You can use the query params to filter your results. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_EXECUTION_LIST, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('queries', [], new Logs(), '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(', ', Executions::ALLOWED_ATTRIBUTES), true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $siteId, array $queries, Response $response, Database $dbForProject) + { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty() || !$site->getAttribute('enabled')) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + // Set internal queries + $queries[] = Query::equal('resourceInternalId', [$site->getInternalId()]); + $queries[] = Query::equal('resourceType', ['sites']); + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + if ($cursor) { + /** @var Query $cursor */ + + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $logId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('executions', $logId); + + if ($cursorDocument->isEmpty() || $cursorDocument->getAttribute('resourceType') !== 'sites') { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Log '{$logId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + + $results = $dbForProject->find('executions', $queries); + $total = $dbForProject->count('executions', $filterQueries, APP_LIMIT_COUNT); + + $response->dynamic(new Document([ + 'executions' => $results, + 'total' => $total, + ]), Response::MODEL_EXECUTION_LIST); // TODO: Update response model + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php new file mode 100644 index 0000000000..c91ec449be --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php @@ -0,0 +1,205 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Sites; + +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\Platform\Modules\Compute\Validator\Specification; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Database\Validator\CustomId; +use Appwrite\Utopia\Response; +use Utopia\App; +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\System\System; +use Utopia\Validator\Boolean; +use Utopia\Validator\Range; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; + +class Create extends Base +{ + use HTTP; + + public static function getName() + { + return 'createSite'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/sites') + ->desc('Create site') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('event', 'sites.[siteId].create') + ->label('audits.event', 'site.create') + ->label('audits.resource', 'site/{response.$id}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'create', + description: <<<EOT + Create a new site. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_SITE, + ) + ], + )) + ->param('siteId', '', new CustomId(), '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.') + ->param('name', '', new Text(128), 'Site name. Max length: 128 chars.') + ->param('framework', '', new WhiteList(\array_keys(Config::getParam('frameworks')), true), 'Sites framework.') + ->param('enabled', true, new Boolean(), '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.', true) + ->param('logging', true, new Boolean(), 'When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.', true) + ->param('timeout', 30, new Range(1, (int) System::getEnv('_APP_SITES_TIMEOUT', 30)), 'Maximum request time in seconds.', true) + ->param('installCommand', '', new Text(8192, 0), 'Install Command.', true) + ->param('buildCommand', '', new Text(8192, 0), 'Build Command.', true) + ->param('outputDirectory', '', new Text(8192, 0), 'Output Directory for site.', true) + ->param('buildRuntime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Runtime to use during build step.') + ->param('adapter', '', new WhiteList(['static', 'ssr']), 'Framework adapter defining rendering strategy. Allowed values are: static, ssr', true) + ->param('installationId', '', new Text(128, 0), 'Appwrite Installation ID for VCS (Version Control System) deployment.', true) + ->param('fallbackFile', '', new Text(255, 0), 'Fallback file for single page application sites.', true) + ->param('providerRepositoryId', '', new Text(128, 0), 'Repository ID of the repo linked to the site.', true) + ->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the site.', true) + ->param('providerSilentMode', false, new Boolean(), '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.', true) + ->param('providerRootDirectory', '', new Text(128, 0), 'Path to site code in the linked repo.', true) + ->param('specification', APP_COMPUTE_SPECIFICATION_DEFAULT, fn (array $plan) => new Specification( + $plan, + Config::getParam('specifications', []), + App::getEnv('_APP_COMPUTE_CPUS', APP_COMPUTE_CPUS_DEFAULT), + App::getEnv('_APP_COMPUTE_MEMORY', APP_COMPUTE_MEMORY_DEFAULT) + ), 'Framework specification for the site and builds.', true, ['plan']) + ->inject('response') + ->inject('dbForProject') + ->inject('project') + ->inject('queueForEvents') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $name, + string $framework, + bool $enabled, + bool $logging, + int $timeout, + string $installCommand, + string $buildCommand, + string $outputDirectory, + string $buildRuntime, + string $adapter, + string $installationId, + string $fallbackFile, + string $providerRepositoryId, + string $providerBranch, + bool $providerSilentMode, + string $providerRootDirectory, + string $specification, + Response $response, + Database $dbForProject, + Document $project, + Event $queueForEvents, + Database $dbForPlatform + ) { + if (!empty($adapter)) { + $configFramework = Config::getParam('frameworks')[$framework] ?? []; + $adapters = \array_keys($configFramework['adapters'] ?? []); + $validator = new WhiteList($adapters, true); + if (!$validator->isValid($adapter)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Adapter not supported for the selected framework.'); + } + } + + $siteId = ($siteId == 'unique()') ? ID::unique() : $siteId; + + $installation = $dbForPlatform->getDocument('installations', $installationId); + + if (!empty($installationId) && $installation->isEmpty()) { + throw new Exception(Exception::INSTALLATION_NOT_FOUND); + } + + if (!empty($providerRepositoryId) && (empty($installationId) || empty($providerBranch))) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'When connecting to VCS (Version Control System), you need to provide "installationId" and "providerBranch".'); + } + + $site = $dbForProject->createDocument('sites', new Document([ + '$id' => $siteId, + 'enabled' => $enabled, + 'live' => true, + 'logging' => $logging, + 'name' => $name, + 'framework' => $framework, + 'deploymentInternalId' => '', + 'deploymentId' => '', + 'timeout' => $timeout, + 'installCommand' => $installCommand, + 'buildCommand' => $buildCommand, + 'outputDirectory' => $outputDirectory, + 'search' => implode(' ', [$siteId, $name, $framework]), + 'fallbackFile' => $fallbackFile, + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getInternalId(), + 'providerRepositoryId' => $providerRepositoryId, + 'repositoryId' => '', + 'repositoryInternalId' => '', + 'providerBranch' => $providerBranch, + 'providerRootDirectory' => $providerRootDirectory, + 'providerSilentMode' => $providerSilentMode, + 'specification' => $specification, + 'buildRuntime' => $buildRuntime, + 'adapter' => $adapter, + ])); + + // Git connect logic + if (!empty($providerRepositoryId)) { + $teamId = $project->getAttribute('teamId', ''); + + $repository = $dbForPlatform->createDocument('repositories', new Document([ + '$id' => ID::unique(), + '$permissions' => [ + Permission::read(Role::team(ID::custom($teamId))), + Permission::update(Role::team(ID::custom($teamId), 'owner')), + Permission::update(Role::team(ID::custom($teamId), 'developer')), + Permission::delete(Role::team(ID::custom($teamId), 'owner')), + Permission::delete(Role::team(ID::custom($teamId), 'developer')), + ], + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getInternalId(), + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'providerRepositoryId' => $providerRepositoryId, + 'resourceId' => $site->getId(), + 'resourceInternalId' => $site->getInternalId(), + 'resourceType' => 'site', + 'providerPullRequestIds' => [] + ])); + + $site->setAttribute('repositoryId', $repository->getId()); + $site->setAttribute('repositoryInternalId', $repository->getInternalId()); + } + + $site = $dbForProject->updateDocument('sites', $site->getId(), $site); + + $queueForEvents->setParam('siteId', $site->getId()); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($site, Response::MODEL_SITE); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Delete.php new file mode 100644 index 0000000000..68573d6674 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Delete.php @@ -0,0 +1,88 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Sites; + +use Appwrite\Event\Delete as DeleteEvent; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Delete extends Base +{ + use HTTP; + + public static function getName() + { + return 'deleteSite'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/sites/:siteId') + ->desc('Delete site') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('event', 'sites.[siteId].delete') + ->label('audits.event', 'site.delete') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'delete', + description: <<<EOT + Delete a site by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForDeletes') + ->inject('queueForEvents') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + Response $response, + Database $dbForProject, + DeleteEvent $queueForDeletes, + Event $queueForEvents + ) { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + if (!$dbForProject->deleteDocument('sites', $site->getId())) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove site from DB'); + } + + $queueForDeletes + ->setType(DELETE_TYPE_DOCUMENT) + ->setDocument($site); + + $queueForEvents->setParam('siteId', $site->getId()); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php new file mode 100644 index 0000000000..7cfe1a50a2 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -0,0 +1,124 @@ +<?php + +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Update extends Base +{ + use HTTP; + + public static function getName() + { + return 'updateSiteDeployment'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH) + ->setHttpPath('/v1/sites/:siteId/deployment') + ->desc('Update site\'s deployment') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('event', 'sites.[siteId].deployments.[deploymentId].update') + ->label('audits.event', 'deployment.update') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'updateSiteDeployment', + description: <<<EOT + Update the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SITE, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('deploymentId', '', new UID(), 'Deployment ID.') + ->inject('project') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('dbForPlatform') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $deploymentId, + Document $project, + Response $response, + Database $dbForProject, + Event $queueForEvents, + Database $dbForPlatform + ) { + $site = $dbForProject->getDocument('sites', $siteId); + $deployment = $dbForProject->getDocument('deployments', $deploymentId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + if ($deployment->isEmpty()) { + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); + } + + if ($deployment->getAttribute('status') !== 'ready') { + 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(), + 'deploymentScreenshotDark' => $deployment->getAttribute('screenshotDark', ''), + 'deploymentScreenshotLight' => $deployment->getAttribute('screenshotLight', ''), + 'deploymentCreatedAt' => $deployment->getCreatedAt(), + ]))); + + $queries = [ + Query::equal('trigger', 'manual'), + Query::equal("type", ["deployment"]), + Query::equal("deploymentResourceType", ["site"]), + Query::equal("deploymentResourceInternalId", [$site->getInternalId()]), + ]; + + 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()) + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); + }); + + $queueForEvents + ->setParam('siteId', $site->getId()) + ->setParam('deploymentId', $deployment->getId()); + + $response->dynamic($site, Response::MODEL_SITE); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Get.php new file mode 100644 index 0000000000..103ab3f751 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Get.php @@ -0,0 +1,64 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Sites; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Get extends Base +{ + use HTTP; + + public static function getName() + { + return 'getSite'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/:siteId') + ->desc('Get site') + ->groups(['api', 'sites']) + ->label('scope', 'sites.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'get', + description: <<<EOT + Get a site by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SITE, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $siteId, Response $response, Database $dbForProject) + { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $response->dynamic($site, Response::MODEL_SITE); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php new file mode 100644 index 0000000000..de220e174c --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php @@ -0,0 +1,282 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Sites; + +use Appwrite\Event\Build; +use Appwrite\Event\Event; +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\Platform\Modules\Compute\Validator\Specification; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Executor\Executor; +use Utopia\App; +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Swoole\Request; +use Utopia\System\System; +use Utopia\Validator\Boolean; +use Utopia\Validator\Range; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; +use Utopia\VCS\Adapter\Git\GitHub; + +class Update extends Base +{ + use HTTP; + + public static function getName() + { + return 'updateSite'; + } + + public function __construct() + { + $this->setHttpMethod(Action::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/sites/:siteId') + ->desc('Update site') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('event', 'sites.[siteId].update') + ->label('audits.event', 'sites.update') + ->label('audits.resource', 'site/{response.$id}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'update', + description: <<<EOT + Update site by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SITE, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('name', '', new Text(128), 'Site name. Max length: 128 chars.') + ->param('framework', '', new WhiteList(\array_keys(Config::getParam('frameworks')), true), 'Sites framework.') + ->param('enabled', true, new Boolean(), '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.', true) + ->param('logging', true, new Boolean(), 'When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.', true) + ->param('timeout', 30, new Range(1, (int) System::getEnv('_APP_SITES_TIMEOUT', 30)), 'Maximum request time in seconds.', true) + ->param('installCommand', '', new Text(8192, 0), 'Install Command.', true) + ->param('buildCommand', '', new Text(8192, 0), 'Build Command.', true) + ->param('outputDirectory', '', new Text(8192, 0), 'Output Directory for site.', true) + ->param('buildRuntime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Runtime to use during build step.', true) + ->param('adapter', '', new WhiteList(['static', 'ssr']), 'Framework adapter defining rendering strategy. Allowed values are: static, ssr', true) + ->param('fallbackFile', '', new Text(255, 0), 'Fallback file for single page application sites.', true) + ->param('installationId', '', new Text(128, 0), 'Appwrite Installation ID for VCS (Version Control System) deployment.', true) + ->param('providerRepositoryId', '', new Text(128, 0), 'Repository ID of the repo linked to the site.', true) + ->param('providerBranch', '', new Text(128, 0), 'Production branch for the repo linked to the site.', true) + ->param('providerSilentMode', false, new Boolean(), '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.', true) + ->param('providerRootDirectory', '', new Text(128, 0), 'Path to site code in the linked repo.', true) + ->param('specification', APP_COMPUTE_SPECIFICATION_DEFAULT, fn (array $plan) => new Specification( + $plan, + Config::getParam('specifications', []), + App::getEnv('_APP_COMPUTE_CPUS', APP_COMPUTE_CPUS_DEFAULT), + App::getEnv('_APP_COMPUTE_MEMORY', APP_COMPUTE_MEMORY_DEFAULT) + ), 'Framework specification for the site and builds.', true, ['plan']) + ->inject('request') + ->inject('response') + ->inject('dbForProject') + ->inject('project') + ->inject('queueForEvents') + ->inject('queueForBuilds') + ->inject('dbForPlatform') + ->inject('gitHub') + ->inject('executor') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $name, + string $framework, + bool $enabled, + bool $logging, + int $timeout, + string $installCommand, + string $buildCommand, + string $outputDirectory, + string $buildRuntime, + string $adapter, + string $fallbackFile, + string $installationId, + ?string $providerRepositoryId, + string $providerBranch, + bool $providerSilentMode, + string $providerRootDirectory, + string $specification, + Request $request, + Response $response, + Database $dbForProject, + Document $project, + Event $queueForEvents, + Build $queueForBuilds, + Database $dbForPlatform, + GitHub $github, + Executor $executor + ) { + if (!empty($adapter)) { + $configFramework = Config::getParam('frameworks')[$framework] ?? []; + $adapters = \array_keys($configFramework['adapters'] ?? []); + $validator = new WhiteList($adapters, true); + if (!$validator->isValid($adapter)) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Adapter not supported for the selected framework.'); + } + } + + // TODO: If only branch changes, re-deploy + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $installation = $dbForPlatform->getDocument('installations', $installationId); + + if (!empty($installationId) && $installation->isEmpty()) { + throw new Exception(Exception::INSTALLATION_NOT_FOUND); + } + + if (!empty($providerRepositoryId) && (empty($installationId) || empty($providerBranch))) { + throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'When connecting to VCS (Version Control System), you need to provide "installationId" and "providerBranch".'); + } + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + if (empty($framework)) { + $framework = $site->getAttribute('framework'); + } + + $enabled ??= $site->getAttribute('enabled', true); + + $repositoryId = $site->getAttribute('repositoryId', ''); + $repositoryInternalId = $site->getAttribute('repositoryInternalId', ''); + + $isConnected = !empty($site->getAttribute('providerRepositoryId', '')); + + // 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('resourceType', ['site']), + Query::limit(100), + ]); + + foreach ($repositories as $repository) { + $dbForPlatform->deleteDocument('repositories', $repository->getId()); + } + + $providerRepositoryId = ''; + $installationId = ''; + $providerBranch = ''; + $providerRootDirectory = ''; + $providerSilentMode = true; + $repositoryId = ''; + $repositoryInternalId = ''; + } + + // Git connect logic + if (!$isConnected && !empty($providerRepositoryId)) { + $teamId = $project->getAttribute('teamId', ''); + + $repository = $dbForPlatform->createDocument('repositories', new Document([ + '$id' => ID::unique(), + '$permissions' => [ + Permission::read(Role::team(ID::custom($teamId))), + Permission::update(Role::team(ID::custom($teamId), 'owner')), + Permission::update(Role::team(ID::custom($teamId), 'developer')), + Permission::delete(Role::team(ID::custom($teamId), 'owner')), + Permission::delete(Role::team(ID::custom($teamId), 'developer')), + ], + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getInternalId(), + 'projectId' => $project->getId(), + 'projectInternalId' => $project->getInternalId(), + 'providerRepositoryId' => $providerRepositoryId, + 'resourceId' => $site->getId(), + 'resourceInternalId' => $site->getInternalId(), + 'resourceType' => 'site', + 'providerPullRequestIds' => [] + ])); + + $repositoryId = $repository->getId(); + $repositoryInternalId = $repository->getInternalId(); + } + + $live = true; + + if ( + $site->getAttribute('name') !== $name || + $site->getAttribute('buildCommand') !== $buildCommand || + $site->getAttribute('installCommand') !== $installCommand || + $site->getAttribute('outputDirectory') !== $outputDirectory || + $site->getAttribute('providerRootDirectory') !== $providerRootDirectory || + $site->getAttribute('framework') !== $framework + ) { + $live = false; + } + + // Enforce Cold Start if spec limits change. + if ($site->getAttribute('specification') !== $specification && !empty($site->getAttribute('deploymentId'))) { + try { + $executor->deleteRuntime($project->getId(), $site->getAttribute('deploymentId')); + } catch (\Throwable $th) { + // Don't throw if the deployment doesn't exist + if ($th->getCode() !== 404) { + throw $th; + } + } + } + + $site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [ + 'name' => $name, + 'framework' => $framework, + 'enabled' => $enabled, + 'logging' => $logging, + 'live' => $live, + 'timeout' => $timeout, + 'installCommand' => $installCommand, + 'buildCommand' => $buildCommand, + 'outputDirectory' => $outputDirectory, + 'installationId' => $installation->getId(), + 'installationInternalId' => $installation->getInternalId(), + 'providerRepositoryId' => $providerRepositoryId, + 'repositoryId' => $repositoryId, + 'repositoryInternalId' => $repositoryInternalId, + 'providerBranch' => $providerBranch, + 'providerRootDirectory' => $providerRootDirectory, + 'providerSilentMode' => $providerSilentMode, + 'specification' => $specification, + 'search' => implode(' ', [$siteId, $name, $framework]), + 'buildRuntime' => $buildRuntime, + 'adapter' => $adapter, + 'fallbackFile' => $fallbackFile, + ]))); + + // Redeploy logic + if (!$isConnected && !empty($providerRepositoryId)) { + $this->redeployVcsFunction($request, $site, $project, $installation, $dbForProject, $queueForBuilds, new Document(), $github, true); + } + + $queueForEvents->setParam('siteId', $site->getId()); + + $response->dynamic($site, Response::MODEL_SITE); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php new file mode 100644 index 0000000000..3237eba0be --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php @@ -0,0 +1,104 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Sites; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Database\Validator\Queries\Sites; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Exception\Query as QueryException; +use Utopia\Database\Query; +use Utopia\Database\Validator\Query\Cursor; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Text; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listSites'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites') + ->desc('List sites') + ->groups(['api', 'sites']) + ->label('scope', 'sites.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'list', + description: <<<EOT + Get a list of all the project's sites. You can use the query params to filter your results. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SITE_LIST, + ) + ] + )) + ->param('queries', [], new Sites(), '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(', ', Sites::ALLOWED_ATTRIBUTES), true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(array $queries, string $search, Response $response, Database $dbForProject) + { + try { + $queries = Query::parseQueries($queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); + if ($cursor) { + /** @var Query $cursor */ + + $validator = new Cursor(); + if (!$validator->isValid($cursor)) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription()); + } + + $siteId = $cursor->getValue(); + $cursorDocument = $dbForProject->getDocument('sites', $siteId); + + if ($cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Site '{$siteId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $filterQueries = Query::groupByType($queries)['filters']; + + $response->dynamic(new Document([ + 'sites' => $dbForProject->find('sites', $queries), + 'total' => $dbForProject->count('sites', $filterQueries, APP_LIMIT_COUNT), + ]), Response::MODEL_SITE_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Specifications/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Specifications/XList.php new file mode 100644 index 0000000000..63ee7bec10 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Specifications/XList.php @@ -0,0 +1,76 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Specifications; + +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +use Utopia\Database\Document; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\System\System; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listSpecifications'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/specifications') + ->groups(['api', 'sites']) + ->desc('List specifications') + ->label('scope', 'sites.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'listSpecifications', + description: <<<EOT + List allowed site specifications for this instance. + EOT, + auth: [AuthType::KEY, AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_SPECIFICATION_LIST, + ) + ] + )) + ->inject('response') + ->inject('plan') + ->callback([$this, 'action']); + } + + public function action(Response $response, array $plan) + { + $allSpecs = Config::getParam('specifications', []); + + $specs = []; + foreach ($allSpecs as $spec) { + $spec['enabled'] = true; + + if (array_key_exists('specifications', $plan)) { + $spec['enabled'] = in_array($spec['slug'], $plan['specifications']); + } + + // Only add specs that are within the limits set by environment variables + if ($spec['cpus'] <= System::getEnv('_APP_COMPUTE_CPUS', 1) && $spec['memory'] <= System::getEnv('_APP_COMPUTE_MEMORY', 512)) { + $specs[] = $spec; + } + } + + $response->dynamic(new Document([ + 'specifications' => $specs, + 'total' => count($specs) + ]), Response::MODEL_SPECIFICATION_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Templates/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Templates/Get.php new file mode 100644 index 0000000000..25183d768a --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Templates/Get.php @@ -0,0 +1,69 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Templates; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +use Utopia\Database\Document; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Text; + +class Get extends Base +{ + use HTTP; + + public static function getName() + { + return 'getTemplate'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/templates/:templateId') + ->desc('Get site template') + ->groups(['api']) + ->label('scope', 'public') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'getTemplate', + description: <<<EOT + Get a site template using ID. You can use template details in [createSite](/docs/references/cloud/server-nodejs/sites#create) method. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEMPLATE_SITE, + ) + ] + )) + ->param('templateId', '', new Text(128), 'Template ID.') + ->inject('response') + ->callback([$this, 'action']); + } + + public function action(string $templateId, Response $response) + { + $templates = Config::getParam('templates-site', []); + + $allowedTemplates = \array_filter($templates, function ($item) use ($templateId) { + return $item['key'] === $templateId; + }); + $template = array_shift($allowedTemplates); + + if (empty($template)) { + throw new Exception(Exception::SITE_TEMPLATE_NOT_FOUND); + } + + $response->dynamic(new Document($template), Response::MODEL_TEMPLATE_SITE); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php new file mode 100644 index 0000000000..e73f89d726 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Templates/XList.php @@ -0,0 +1,90 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Templates; + +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +use Utopia\Database\Document; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\ArrayList; +use Utopia\Validator\Range; +use Utopia\Validator\WhiteList; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listTemplates'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/templates') + ->desc('List templates') + ->groups(['api']) + ->label('scope', 'public') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'listTemplates', + description: <<<EOT + List available site templates. You can use template details in [createSite](/docs/references/cloud/server-nodejs/sites#create) method. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_TEMPLATE_SITE_LIST, + ) + ] + )) + ->param('frameworks', [], new ArrayList(new WhiteList(\array_keys(Config::getParam('frameworks')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of frameworks allowed for filtering site templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' frameworks are allowed.', true) + ->param('useCases', [], new ArrayList(new WhiteList(['dev-tools', 'starter', 'databases', 'ai', 'messaging', 'utilities']), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of use cases allowed for filtering site templates. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' use cases are allowed.', true) + ->param('limit', 25, new Range(1, 5000), 'Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.', true) + ->param('offset', 0, new Range(0, 5000), 'Offset the list of returned templates. Maximum offset is 5000.', true) + ->inject('response') + ->callback([$this, 'action']); + } + + public function action( + array $frameworks, + array $usecases, + int $limit, + int $offset, + Response $response + ) { + $templates = Config::getParam('templates-site', []); + + if (!empty($frameworks)) { + $templates = \array_filter($templates, function ($template) use ($frameworks) { + return \count(\array_intersect($frameworks, \array_column($template['frameworks'], 'key'))) > 0; + }); + } + + if (!empty($usecases)) { + $templates = \array_filter($templates, function ($template) use ($usecases) { + return \count(\array_intersect($usecases, $template['useCases'])) > 0; + }); + } + + \usort($templates, function ($a, $b) { + return $b['score'] <=> $a['score']; + }); + + $total = \count($templates); + $templates = \array_slice($templates, $offset, $limit); + $response->dynamic(new Document([ + 'templates' => $templates, + 'total' => $total, + ]), Response::MODEL_TEMPLATE_SITE_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php new file mode 100644 index 0000000000..158674aeba --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -0,0 +1,172 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Usage; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +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; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\WhiteList; + +class Get extends Base +{ + use HTTP; + + public static function getName() + { + return 'getUsage'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/:siteId/usage') + ->desc('Get site usage') + ->groups(['api', 'sites', 'usage']) + ->label('scope', 'sites.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'getUsage', + description: <<<EOT + 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. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_SITE, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site ID.') + ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $range, + Response $response, + Database $dbForProject + ) { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $periods = Config::getParam('usage', []); + $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), + + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $result = $dbForProject->findOne('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', ['inf']) + ]); + + $stats[$metric]['total'] = $result['value'] ?? 0; + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', [$period]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric]['data'] = []; + foreach ($results as $result) { + $stats[$metric]['data'][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['data'] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric]['data'][] = [ + 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + + $buildsTimeTotal = $usage[$metrics[4]]['total'] ?? 0; + $buildsTotal = $usage[$metrics[2]]['total'] ?? 0; + $response->dynamic(new Document([ + 'range' => $range, + 'deploymentsTotal' => $usage[$metrics[0]]['total'], + 'deploymentsStorageTotal' => $usage[$metrics[1]]['total'], + 'buildsTotal' => $buildsTotal, + 'buildsStorageTotal' => $usage[$metrics[3]]['total'], + 'buildsTimeTotal' => $buildsTimeTotal, + 'buildsTimeAverage' => $buildsTotal === 0 ? 0 : (int) ($buildsTimeTotal / $buildsTotal), + 'executionsTotal' => $usage[$metrics[5]]['total'], + 'executionsTimeTotal' => $usage[$metrics[6]]['total'], + 'buildsMbSecondsTotal' => $usage[$metrics[7]]['total'], + 'executionsMbSecondsTotal' => $usage[$metrics[8]]['total'], + 'buildsSuccessTotal' => $usage[$metrics[9]]['total'], + 'buildsFailedTotal' => $usage[$metrics[10]]['total'], + 'requestsTotal' => $usage[$metrics[11]]['total'], + 'inboundTotal' => $usage[$metrics[12]]['total'], + 'outboundTotal' => $usage[$metrics[13]]['total'], + 'deployments' => $usage[$metrics[0]]['data'], + 'deploymentsStorage' => $usage[$metrics[1]]['data'], + 'builds' => $usage[$metrics[2]]['data'], + 'buildsStorage' => $usage[$metrics[3]]['data'], + 'buildsTime' => $usage[$metrics[4]]['data'], + 'executions' => $usage[$metrics[5]]['data'], + 'executionsTime' => $usage[$metrics[6]]['data'], + 'buildsMbSeconds' => $usage[$metrics[7]]['data'], + 'executionsMbSeconds' => $usage[$metrics[8]]['data'], + 'buildsSuccess' => $usage[$metrics[9]]['data'], + 'buildsFailed' => $usage[$metrics[10]]['data'], + 'requests' => $usage[$metrics[11]]['data'], + 'inbound' => $usage[$metrics[12]]['data'], + 'outbound' => $usage[$metrics[13]]['data'], + ]), Response::MODEL_USAGE_SITE); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php new file mode 100644 index 0000000000..6f830b665e --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/XList.php @@ -0,0 +1,157 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Usage; + +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Config\Config; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\WhiteList; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'getSitesUsage'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/usage') + ->desc('Get sites usage') + ->groups(['api', 'sites', 'usage']) + ->label('scope', 'sites.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'listUsage', + description: <<<EOT + 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. + EOT, + auth: [AuthType::ADMIN], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_USAGE_SITES, + ) + ] + )) + ->param('range', '30d', new WhiteList(['24h', '30d', '90d']), 'Date range.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $range, Response $response, Database $dbForProject) + { + $periods = Config::getParam('usage', []); + $stats = $usage = []; + $days = $periods[$range]; + $metrics = [ + METRIC_SITES, + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_DEPLOYMENTS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_STORAGE), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_COMPUTE), + 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_BUILDS_MB_SECONDS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_SUCCESS), + str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_FAILED), + METRIC_SITES_REQUESTS, + METRIC_SITES_INBOUND, + METRIC_SITES_OUTBOUND, + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $result = $dbForProject->findOne('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', ['inf']) + ]); + + $stats[$metric]['total'] = $result['value'] ?? 0; + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('metric', [$metric]), + Query::equal('period', [$period]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric]['data'] = []; + foreach ($results as $result) { + $stats[$metric]['data'][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric]['total'] = $stats[$metric]['total']; + $usage[$metric]['data'] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric]['data'][] = [ + 'value' => $stats[$metric]['data'][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + $response->dynamic(new Document([ + 'range' => $range, + 'sitesTotal' => $usage[$metrics[0]]['total'], + 'deploymentsTotal' => $usage[$metrics[1]]['total'], + 'deploymentsStorageTotal' => $usage[$metrics[2]]['total'], + 'buildsTotal' => $usage[$metrics[3]]['total'], + 'buildsStorageTotal' => $usage[$metrics[4]]['total'], + 'buildsTimeTotal' => $usage[$metrics[5]]['total'], + 'executionsTotal' => $usage[$metrics[6]]['total'], + 'executionsTimeTotal' => $usage[$metrics[7]]['total'], + 'buildsMbSecondsTotal' => $usage[$metrics[8]]['total'], + 'executionsMbSecondsTotal' => $usage[$metrics[9]]['total'], + 'buildsSuccessTotal' => $usage[$metrics[10]]['total'], + 'buildsFailedTotal' => $usage[$metrics[11]]['total'], + 'requestsTotal' => $usage[$metrics[12]]['total'], + 'inboundTotal' => $usage[$metrics[13]]['total'], + 'outboundTotal' => $usage[$metrics[14]]['total'], + 'sites' => $usage[$metrics[0]]['data'], + 'deployments' => $usage[$metrics[1]]['data'], + 'deploymentsStorage' => $usage[$metrics[2]]['data'], + 'builds' => $usage[$metrics[3]]['data'], + 'buildsStorage' => $usage[$metrics[4]]['data'], + 'buildsTime' => $usage[$metrics[5]]['data'], + 'executions' => $usage[$metrics[6]]['data'], + 'executionsTime' => $usage[$metrics[7]]['data'], + 'buildsMbSeconds' => $usage[$metrics[8]]['data'], + 'executionsMbSeconds' => $usage[$metrics[9]]['data'], + 'buildsSuccess' => $usage[$metrics[10]]['data'], + 'buildsFailed' => $usage[$metrics[11]]['data'], + 'requests' => $usage[$metrics[12]]['data'], + 'inbound' => $usage[$metrics[13]]['data'], + 'outbound' => $usage[$metrics[14]]['data'], + ]), Response::MODEL_USAGE_SITES); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php new file mode 100644 index 0000000000..13e7f80513 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php @@ -0,0 +1,108 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Variables; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Exception\Duplicate as DuplicateException; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; + +class Create extends Base +{ + use HTTP; + + public static function getName() + { + return 'createVariable'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) + ->setHttpPath('/v1/sites/:siteId/variables') + ->desc('Create variable') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('audits.event', 'variable.create') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'createVariable', + description: <<<EOT + Create a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_CREATED, + model: Response::MODEL_VARIABLE, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site unique ID.', false) + ->param('key', null, new Text(Database::LENGTH_KEY), 'Variable key. Max length: ' . Database::LENGTH_KEY . ' chars.', false) + ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', false) + ->param('secret', true, new Boolean(), 'Secret variables can be updated or deleted, but only sites can read them during build and runtime.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('project') + ->callback([$this, 'action']); + } + + public function action(string $siteId, string $key, string $value, bool $secret, Response $response, Database $dbForProject, Document $project) + { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $variableId = ID::unique(); + + $teamId = $project->getAttribute('teamId', ''); + $variable = new Document([ + '$id' => $variableId, + '$permissions' => [ + Permission::read(Role::team(ID::custom($teamId))), + Permission::update(Role::team(ID::custom($teamId), 'owner')), + Permission::update(Role::team(ID::custom($teamId), 'developer')), + Permission::delete(Role::team(ID::custom($teamId), 'owner')), + Permission::delete(Role::team(ID::custom($teamId), 'developer')), + ], + 'resourceInternalId' => $site->getInternalId(), + 'resourceId' => $site->getId(), + 'resourceType' => 'site', + 'key' => $key, + 'value' => $value, + 'secret' => $secret, + 'search' => implode(' ', [$variableId, $site->getId(), $key, 'site']), + ]); + + try { + $variable = $dbForProject->createDocument('variables', $variable); + } catch (DuplicateException $th) { + throw new Exception(Exception::VARIABLE_ALREADY_EXISTS); + } + + $dbForProject->updateDocument('sites', $site->getId(), $site->setAttribute('live', false)); + + $response + ->setStatusCode(Response::STATUS_CODE_CREATED) + ->dynamic($variable, Response::MODEL_VARIABLE); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php new file mode 100644 index 0000000000..458a34438e --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php @@ -0,0 +1,82 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Variables; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\ContentType; +use Appwrite\SDK\Method; +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Utopia\Database\Database; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Delete extends Base +{ + use HTTP; + + public static function getName() + { + return 'deleteVariable'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_DELETE) + ->setHttpPath('/v1/sites/:siteId/variables/:variableId') + ->desc('Delete variable') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('audits.event', 'variable.delete') + ->label('audits.resource', 'site/{request.siteId}') + ->label('sdk', new Method( + namespace: 'sites', + name: 'deleteVariable', + description: <<<EOT + Delete a variable by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::NONE + )) + ->param('siteId', '', new UID(), 'Site unique ID.', false) + ->param('variableId', '', new UID(), 'Variable unique ID.', false) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $siteId, string $variableId, Response $response, Database $dbForProject) + { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $variable = $dbForProject->getDocument('variables', $variableId); + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $site->getInternalId() || $variable->getAttribute('resourceType') !== 'site') { + throw new Exception(Exception::VARIABLE_NOT_FOUND); + } + + if ($variable === false || $variable->isEmpty()) { + throw new Exception(Exception::VARIABLE_NOT_FOUND); + } + + $dbForProject->deleteDocument('variables', $variable->getId()); + + $dbForProject->updateDocument('sites', $site->getId(), $site->setAttribute('live', false)); + + $response->noContent(); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php new file mode 100644 index 0000000000..1e56cc5b15 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php @@ -0,0 +1,82 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Variables; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class Get extends Base +{ + use HTTP; + + public static function getName() + { + return 'getVariable'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/:siteId/variables/:variableId') + ->desc('Get variable') + ->groups(['api', 'sites']) + ->label('scope', 'sites.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label( + 'sdk', + new Method( + namespace: 'sites', + name: 'getVariable', + description: <<<EOT + Get a variable by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE, + ) + ], + ) + ) + ->param('siteId', '', new UID(), 'Site unique ID.', false) + ->param('variableId', '', new UID(), 'Variable unique ID.', false) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action(string $siteId, string $variableId, Response $response, Database $dbForProject) + { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $variable = $dbForProject->getDocument('variables', $variableId); + if ( + $variable === false || + $variable->isEmpty() || + $variable->getAttribute('resourceInternalId') !== $site->getInternalId() || + $variable->getAttribute('resourceType') !== 'site' + ) { + throw new Exception(Exception::VARIABLE_NOT_FOUND); + } + + if ($variable === false || $variable->isEmpty()) { + throw new Exception(Exception::VARIABLE_NOT_FOUND); + } + + $response->dynamic($variable, Response::MODEL_VARIABLE); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php new file mode 100644 index 0000000000..fa37432b5c --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php @@ -0,0 +1,103 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Variables; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Exception\Duplicate as DuplicateException; +use Utopia\Database\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; +use Utopia\Validator\Boolean; +use Utopia\Validator\Text; + +class Update extends Base +{ + use HTTP; + + public static function getName() + { + return 'updateVariable'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_PUT) + ->setHttpPath('/v1/sites/:siteId/variables/:variableId') + ->desc('Update variable') + ->groups(['api', 'sites']) + ->label('scope', 'sites.write') + ->label('audits.event', 'variable.update') + ->label('audits.resource', 'site/{request.siteId}') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label('sdk', new Method( + namespace: 'sites', + name: 'updateVariable', + description: <<<EOT + Update variable by its unique ID. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE, + ) + ] + )) + ->param('siteId', '', new UID(), 'Site unique ID.', false) + ->param('variableId', '', new UID(), 'Variable unique ID.', false) + ->param('key', null, new Text(255), 'Variable key. Max length: 255 chars.', false) + ->param('value', null, new Text(8192, 0), 'Variable value. Max length: 8192 chars.', true) + ->param('secret', null, new Boolean(), 'Secret variables can be updated or deleted, but only sites can read them during build and runtime.', true) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + string $variableId, + string $key, + ?string $value, + ?bool $secret, + Response $response, + Database $dbForProject + ) { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $variable = $dbForProject->getDocument('variables', $variableId); + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $site->getInternalId() || $variable->getAttribute('resourceType') !== 'site') { + throw new Exception(Exception::VARIABLE_NOT_FOUND); + } + + if ($variable->getAttribute('secret') === true && $secret === false) { + throw new Exception(Exception::VARIABLE_CANNOT_UNSET_SECRET); + } + + $variable + ->setAttribute('key', $key) + ->setAttribute('value', $value ?? $variable->getAttribute('value')) + ->setAttribute('secret', $secret ?? $variable->getAttribute('secret')) + ->setAttribute('search', implode(' ', [$variableId, $site->getId(), $key, 'site'])); + + try { + $dbForProject->updateDocument('variables', $variable->getId(), $variable); + } catch (DuplicateException $th) { + throw new Exception(Exception::VARIABLE_ALREADY_EXISTS); + } + + $dbForProject->updateDocument('sites', $site->getId(), $site->setAttribute('live', false)); + + $response->dynamic($variable, Response::MODEL_VARIABLE); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/XList.php new file mode 100644 index 0000000000..2cc3fe8e54 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/XList.php @@ -0,0 +1,74 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Http\Variables; + +use Appwrite\Extend\Exception; +use Appwrite\Platform\Modules\Compute\Base; +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\Validator\UID; +use Utopia\Platform\Action; +use Utopia\Platform\Scope\HTTP; + +class XList extends Base +{ + use HTTP; + + public static function getName() + { + return 'listVariables'; + } + + public function __construct() + { + $this + ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) + ->setHttpPath('/v1/sites/:siteId/variables') + ->desc('List variables') + ->groups(['api', 'sites']) + ->label('scope', 'sites.read') + ->label('resourceType', RESOURCE_TYPE_SITES) + ->label( + 'sdk', + new Method( + namespace: 'sites', + name: 'listVariables', + description: <<<EOT + Get a list of all variables of a specific site. + EOT, + auth: [AuthType::KEY], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_VARIABLE_LIST, + ) + ], + ) + ) + ->param('siteId', '', new UID(), 'Site unique ID.', false) + ->inject('response') + ->inject('dbForProject') + ->callback([$this, 'action']); + } + + public function action( + string $siteId, + Response $response, + Database $dbForProject + ) { + $site = $dbForProject->getDocument('sites', $siteId); + + if ($site->isEmpty()) { + throw new Exception(Exception::SITE_NOT_FOUND); + } + + $response->dynamic(new Document([ + 'variables' => $site->getAttribute('vars', []), + 'total' => \count($site->getAttribute('vars', [])), + ]), Response::MODEL_VARIABLE_LIST); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Module.php b/src/Appwrite/Platform/Modules/Sites/Module.php new file mode 100644 index 0000000000..86a6459a86 --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Module.php @@ -0,0 +1,14 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites; + +use Appwrite\Platform\Modules\Sites\Services\Http; +use Utopia\Platform; + +class Module extends Platform\Module +{ + public function __construct() + { + $this->addService('http', new Http()); + } +} diff --git a/src/Appwrite/Platform/Modules/Sites/Services/Http.php b/src/Appwrite/Platform/Modules/Sites/Services/Http.php new file mode 100644 index 0000000000..6bd151f97e --- /dev/null +++ b/src/Appwrite/Platform/Modules/Sites/Services/Http.php @@ -0,0 +1,86 @@ +<?php + +namespace Appwrite\Platform\Modules\Sites\Services; + +use Appwrite\Platform\Modules\Sites\Http\Deployments\Create as CreateDeployment; +use Appwrite\Platform\Modules\Sites\Http\Deployments\Delete as DeleteDeployment; +use Appwrite\Platform\Modules\Sites\Http\Deployments\Download\Get as DownloadDeployment; +use Appwrite\Platform\Modules\Sites\Http\Deployments\Duplicate\Create as CreateDuplicateDeployment; +use Appwrite\Platform\Modules\Sites\Http\Deployments\Get as GetDeployment; +use Appwrite\Platform\Modules\Sites\Http\Deployments\Status\Update as UpdateDeploymentStatus; +use Appwrite\Platform\Modules\Sites\Http\Deployments\Template\Create as CreateTemplateDeployment; +use Appwrite\Platform\Modules\Sites\Http\Deployments\Vcs\Create as CreateVcsDeployment; +use Appwrite\Platform\Modules\Sites\Http\Deployments\XList as ListDeployments; +use Appwrite\Platform\Modules\Sites\Http\Frameworks\XList as ListFrameworks; +use Appwrite\Platform\Modules\Sites\Http\Logs\Delete as DeleteLog; +use Appwrite\Platform\Modules\Sites\Http\Logs\Get as GetLog; +use Appwrite\Platform\Modules\Sites\Http\Logs\XList as ListLogs; +use Appwrite\Platform\Modules\Sites\Http\Sites\Create as CreateSite; +use Appwrite\Platform\Modules\Sites\Http\Sites\Delete as DeleteSite; +use Appwrite\Platform\Modules\Sites\Http\Sites\Deployment\Update as UpdateSiteDeployment; +use Appwrite\Platform\Modules\Sites\Http\Sites\Get as GetSite; +use Appwrite\Platform\Modules\Sites\Http\Sites\Update as UpdateSite; +use Appwrite\Platform\Modules\Sites\Http\Sites\XList as ListSites; +use Appwrite\Platform\Modules\Sites\Http\Specifications\XList as ListSpecifications; +use Appwrite\Platform\Modules\Sites\Http\Templates\Get as GetTemplate; +use Appwrite\Platform\Modules\Sites\Http\Templates\XList as ListTemplates; +use Appwrite\Platform\Modules\Sites\Http\Usage\Get as GetUsage; +use Appwrite\Platform\Modules\Sites\Http\Usage\XList as ListUsage; +use Appwrite\Platform\Modules\Sites\Http\Variables\Create as CreateVariable; +use Appwrite\Platform\Modules\Sites\Http\Variables\Delete as DeleteVariable; +use Appwrite\Platform\Modules\Sites\Http\Variables\Get as GetVariable; +use Appwrite\Platform\Modules\Sites\Http\Variables\Update as UpdateVariable; +use Appwrite\Platform\Modules\Sites\Http\Variables\XList as ListVariables; +use Utopia\Platform\Service; + +class Http extends Service +{ + public function __construct() + { + $this->type = Service::TYPE_HTTP; + // Sites + $this->addAction(CreateSite::getName(), new CreateSite()); + $this->addAction(GetSite::getName(), new GetSite()); + $this->addAction(ListSites::getName(), new ListSites()); + $this->addAction(UpdateSite::getName(), new UpdateSite()); + $this->addAction(DeleteSite::getName(), new DeleteSite()); + + // Frameworks + $this->addAction(ListFrameworks::getName(), new ListFrameworks()); + + + // Deployments + $this->addAction(CreateDeployment::getName(), new CreateDeployment()); + $this->addAction(CreateTemplateDeployment::getName(), new CreateTemplateDeployment()); + $this->addAction(CreateVcsDeployment::getName(), new CreateVcsDeployment()); + $this->addAction(GetDeployment::getName(), new GetDeployment()); + $this->addAction(ListDeployments::getName(), new ListDeployments()); + $this->addAction(UpdateSiteDeployment::getName(), new UpdateSiteDeployment()); + $this->addAction(DeleteDeployment::getName(), new DeleteDeployment()); + $this->addAction(DownloadDeployment::getName(), new DownloadDeployment()); + $this->addAction(CreateDuplicateDeployment::getName(), new CreateDuplicateDeployment()); + $this->addAction(UpdateDeploymentStatus::getName(), new UpdateDeploymentStatus()); + + // Logs + $this->addAction(GetLog::getName(), new GetLog()); + $this->addAction(ListLogs::getName(), new ListLogs()); + $this->addAction(DeleteLog::getName(), new DeleteLog()); + + // Variables + $this->addAction(CreateVariable::getName(), new CreateVariable()); + $this->addAction(GetVariable::getName(), new GetVariable()); + $this->addAction(ListVariables::getName(), new ListVariables()); + $this->addAction(UpdateVariable::getName(), new UpdateVariable()); + $this->addAction(DeleteVariable::getName(), new DeleteVariable()); + + // Templates + $this->addAction(ListTemplates::getName(), new ListTemplates()); + $this->addAction(GetTemplate::getName(), new GetTemplate()); + + // Usage + $this->addAction(ListUsage::getName(), new ListUsage()); + $this->addAction(GetUsage::getName(), new GetUsage()); + + $this->addAction(ListSpecifications::getName(), new ListSpecifications()); + } +} diff --git a/src/Appwrite/Platform/Services/Tasks.php b/src/Appwrite/Platform/Services/Tasks.php index 7a0d5b60ac..3ada193cf7 100644 --- a/src/Appwrite/Platform/Services/Tasks.php +++ b/src/Appwrite/Platform/Services/Tasks.php @@ -6,14 +6,15 @@ use Appwrite\Platform\Tasks\Doctor; use Appwrite\Platform\Tasks\Install; use Appwrite\Platform\Tasks\Maintenance; use Appwrite\Platform\Tasks\Migrate; -use Appwrite\Platform\Tasks\QueueCount; use Appwrite\Platform\Tasks\QueueRetry; use Appwrite\Platform\Tasks\ScheduleExecutions; use Appwrite\Platform\Tasks\ScheduleFunctions; use Appwrite\Platform\Tasks\ScheduleMessages; +use Appwrite\Platform\Tasks\Screenshot; use Appwrite\Platform\Tasks\SDKs; use Appwrite\Platform\Tasks\Specs; use Appwrite\Platform\Tasks\SSL; +use Appwrite\Platform\Tasks\StatsResources; use Appwrite\Platform\Tasks\Upgrade; use Appwrite\Platform\Tasks\Vars; use Appwrite\Platform\Tasks\Version; @@ -29,10 +30,10 @@ class Tasks extends Service ->addAction(Install::getName(), new Install()) ->addAction(Maintenance::getName(), new Maintenance()) ->addAction(Migrate::getName(), new Migrate()) - ->addAction(QueueCount::getName(), new QueueCount()) ->addAction(QueueRetry::getName(), new QueueRetry()) ->addAction(SDKs::getName(), new SDKs()) ->addAction(SSL::getName(), new SSL()) + ->addAction(Screenshot::getName(), new Screenshot()) ->addAction(ScheduleFunctions::getName(), new ScheduleFunctions()) ->addAction(ScheduleExecutions::getName(), new ScheduleExecutions()) ->addAction(ScheduleMessages::getName(), new ScheduleMessages()) @@ -40,6 +41,7 @@ class Tasks extends Service ->addAction(Upgrade::getName(), new Upgrade()) ->addAction(Vars::getName(), new Vars()) ->addAction(Version::getName(), new Version()) + ->addAction(StatsResources::getName(), new StatsResources()) ; } } diff --git a/src/Appwrite/Platform/Services/Workers.php b/src/Appwrite/Platform/Services/Workers.php index 0e79f4257c..5753170082 100644 --- a/src/Appwrite/Platform/Services/Workers.php +++ b/src/Appwrite/Platform/Services/Workers.php @@ -3,7 +3,6 @@ namespace Appwrite\Platform\Services; use Appwrite\Platform\Workers\Audits; -use Appwrite\Platform\Workers\Builds; use Appwrite\Platform\Workers\Certificates; use Appwrite\Platform\Workers\Databases; use Appwrite\Platform\Workers\Deletes; @@ -11,8 +10,9 @@ use Appwrite\Platform\Workers\Functions; use Appwrite\Platform\Workers\Mails; use Appwrite\Platform\Workers\Messaging; use Appwrite\Platform\Workers\Migrations; -use Appwrite\Platform\Workers\Usage; -use Appwrite\Platform\Workers\UsageDump; +use Appwrite\Platform\Workers\StatsResources; +use Appwrite\Platform\Workers\StatsUsage; +use Appwrite\Platform\Workers\StatsUsageDump; use Appwrite\Platform\Workers\Webhooks; use Utopia\Platform\Service; @@ -23,7 +23,6 @@ class Workers extends Service $this->type = Service::TYPE_WORKER; $this ->addAction(Audits::getName(), new Audits()) - ->addAction(Builds::getName(), new Builds()) ->addAction(Certificates::getName(), new Certificates()) ->addAction(Databases::getName(), new Databases()) ->addAction(Deletes::getName(), new Deletes()) @@ -31,10 +30,10 @@ class Workers extends Service ->addAction(Mails::getName(), new Mails()) ->addAction(Messaging::getName(), new Messaging()) ->addAction(Webhooks::getName(), new Webhooks()) - ->addAction(UsageDump::getName(), new UsageDump()) - ->addAction(Usage::getName(), new Usage()) + ->addAction(StatsUsageDump::getName(), new StatsUsageDump()) + ->addAction(StatsUsage::getName(), new StatsUsage()) ->addAction(Migrations::getName(), new Migrations()) - + ->addAction(StatsResources::getName(), new StatsResources()) ; } } diff --git a/src/Appwrite/Platform/Tasks/Doctor.php b/src/Appwrite/Platform/Tasks/Doctor.php index c43afea527..790f1a7290 100644 --- a/src/Appwrite/Platform/Tasks/Doctor.php +++ b/src/Appwrite/Platform/Tasks/Doctor.php @@ -15,6 +15,7 @@ use Utopia\Registry\Registry; use Utopia\Storage\Device\Local; use Utopia\Storage\Storage; use Utopia\System\System; +use Utopia\Validator\IP; class Doctor extends Action { @@ -28,7 +29,7 @@ class Doctor extends Action $this ->desc('Validate server health') ->inject('register') - ->callback(fn (Registry $register) => $this->action($register)); + ->callback([$this, 'action']); } public function action(Registry $register): void @@ -43,19 +44,31 @@ class Doctor extends Action Console::log('[Settings]'); $domain = new Domain(System::getEnv('_APP_DOMAIN')); - if (!$domain->isKnown() || $domain->isTest()) { - Console::log('🔴 Hostname has no public suffix (' . $domain->get() . ')'); + Console::log('🔴 Hostname is not valid (' . $domain->get() . ')'); } else { - Console::log('🟢 Hostname has a public suffix (' . $domain->get() . ')'); + Console::log('🟢 Hostname is valid (' . $domain->get() . ')'); } - $domain = new Domain(System::getEnv('_APP_DOMAIN_TARGET')); - + $domain = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME')); if (!$domain->isKnown() || $domain->isTest()) { - Console::log('🔴 CNAME target has no public suffix (' . $domain->get() . ')'); + Console::log('🔴 CNAME record target is not valid (' . $domain->get() . ')'); } else { - Console::log('🟢 CNAME target has a public suffix (' . $domain->get() . ')'); + Console::log('🟢 CNAME record target is valid (' . $domain->get() . ')'); + } + + $ipv4 = new IP(IP::V4); + if (!$ipv4->isValid(System::getEnv('_APP_DOMAIN_TARGET_A'))) { + Console::log('🔴 A record target is not valid (' . System::getEnv('_APP_DOMAIN_TARGET_A') . ')'); + } else { + Console::log('🟢 A record target is valid (' . System::getEnv('_APP_DOMAIN_TARGET_A') . ')'); + } + + $ipv6 = new IP(IP::V6); + if (!$ipv6->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA'))) { + Console::log('🔴 AAAA record target is not valid (' . System::getEnv('_APP_DOMAIN_TARGET_AAAA') . ')'); + } else { + Console::log('🟢 AAAA record target is valid (' . System::getEnv('_APP_DOMAIN_TARGET_AAAA') . ')'); } if (System::getEnv('_APP_OPENSSL_KEY_V1') === 'your-secret-key' || empty(System::getEnv('_APP_OPENSSL_KEY_V1'))) { @@ -96,10 +109,10 @@ class Doctor extends Action Console::log('🟢 HTTPS force option is enabled'); } - if ('enabled' !== System::getEnv('_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS', 'disabled')) { - Console::log('🔴 HTTPS force option is disabled for function domains'); + if ('enabled' !== System::getEnv('_APP_OPTIONS_ROUTER_FORCE_HTTPS', 'disabled')) { + Console::log('🔴 HTTPS force option is disabled for function/site domains'); } else { - Console::log('🟢 HTTPS force option is enabled for function domains'); + Console::log('🟢 HTTPS force option is enabled for function/site domains'); } $providerConfig = System::getEnv('_APP_LOGGING_CONFIG', ''); diff --git a/src/Appwrite/Platform/Tasks/Install.php b/src/Appwrite/Platform/Tasks/Install.php index 4abd267684..c7b1f72453 100644 --- a/src/Appwrite/Platform/Tasks/Install.php +++ b/src/Appwrite/Platform/Tasks/Install.php @@ -31,7 +31,7 @@ class Install extends Action ->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true) ->param('interactive', 'Y', new Text(1), 'Run an interactive session', true) ->param('no-start', false, new Boolean(true), 'Run an interactive session', true) - ->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive, $noStart) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive, $noStart)); + ->callback([$this, 'action']); } public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive, bool $noStart): void diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index afb38f35fc..198b701044 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -23,13 +23,14 @@ class Maintenance extends Action { $this ->desc('Schedules maintenance tasks and publishes them to our queues') - ->inject('dbForConsole') + ->inject('dbForPlatform') + ->inject('console') ->inject('queueForCertificates') ->inject('queueForDeletes') - ->callback(fn (Database $dbForConsole, Certificate $queueForCertificates, Delete $queueForDeletes) => $this->action($dbForConsole, $queueForCertificates, $queueForDeletes)); + ->callback([$this, 'action']); } - public function action(Database $dbForConsole, Certificate $queueForCertificates, Delete $queueForDeletes): void + public function action(Database $dbForPlatform, Document $console, Certificate $queueForCertificates, Delete $queueForDeletes): void { Console::title('Maintenance V1'); Console::success(APP_NAME . ' maintenance process v1 has started'); @@ -41,93 +42,34 @@ class Maintenance extends Action $cacheRetention = (int) System::getEnv('_APP_MAINTENANCE_RETENTION_CACHE', '2592000'); // 30 days $schedulesDeletionRetention = (int) System::getEnv('_APP_MAINTENANCE_RETENTION_SCHEDULES', '86400'); // 1 Day - Console::loop(function () use ($interval, $cacheRetention, $schedulesDeletionRetention, $usageStatsRetentionHourly, $dbForConsole, $queueForDeletes, $queueForCertificates) { + Console::loop(function () use ($interval, $cacheRetention, $schedulesDeletionRetention, $usageStatsRetentionHourly, $dbForPlatform, $console, $queueForDeletes, $queueForCertificates) { $time = DateTime::now(); Console::info("[{$time}] Notifying workers with maintenance tasks every {$interval} seconds"); - $this->foreachProject($dbForConsole, function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) { - $queueForDeletes->setProject($project); + $dbForPlatform->foreach('projects', function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) { + $queueForDeletes + ->setType(DELETE_TYPE_MAINTENANCE) + ->setProject($project) + ->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) + ->trigger(); + }, [ + Query::limit(100), + ]); - $this->notifyProjects($queueForDeletes, $usageStatsRetentionHourly); - }); + $queueForDeletes + ->setType(DELETE_TYPE_MAINTENANCE) + ->setProject($console) + ->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) + ->trigger(); $this->notifyDeleteConnections($queueForDeletes); - $this->renewCertificates($dbForConsole, $queueForCertificates); + $this->renewCertificates($dbForPlatform, $queueForCertificates); $this->notifyDeleteCache($cacheRetention, $queueForDeletes); $this->notifyDeleteSchedules($schedulesDeletionRetention, $queueForDeletes); }, $interval, $delay); } - /** - * Hook to allow sub-classes to extend project-level maintenance functionality. - */ - protected function notifyProjects(Delete $queueForDeletes, int $usageStatsRetentionHourly): void - { - $this->notifyDeleteTargets($queueForDeletes); - $this->notifyDeleteExecutionLogs($queueForDeletes); - $this->notifyDeleteAbuseLogs($queueForDeletes); - $this->notifyDeleteAuditLogs($queueForDeletes); - $this->notifyDeleteUsageStats($usageStatsRetentionHourly, $queueForDeletes); - $this->notifyDeleteExpiredSessions($queueForDeletes); - } - - protected function foreachProject(Database $dbForConsole, callable $callback): void - { - // TODO: @Meldiron name of this method no longer matches. It does not delete, and it gives whole document - $count = 0; - $chunk = 0; - $limit = 50; - $sum = $limit; - $executionStart = \microtime(true); - - while ($sum === $limit) { - $projects = $dbForConsole->find('projects', [Query::limit($limit), Query::offset($chunk * $limit)]); - - $chunk++; - - /** @var string[] $projectIds */ - $sum = count($projects); - - foreach ($projects as $project) { - $callback($project); - $count++; - } - } - - $executionEnd = \microtime(true); - Console::info("Found {$count} projects " . ($executionEnd - $executionStart) . " seconds"); - } - - private function notifyDeleteExecutionLogs(Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_EXECUTIONS) - ->trigger(); - } - - private function notifyDeleteAbuseLogs(Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_ABUSE) - ->trigger(); - } - - private function notifyDeleteAuditLogs(Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_AUDIT) - ->trigger(); - } - - private function notifyDeleteUsageStats(int $usageStatsRetentionHourly, Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_USAGE) - ->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) - ->trigger(); - } - private function notifyDeleteConnections(Delete $queueForDeletes): void { $queueForDeletes @@ -136,19 +78,13 @@ class Maintenance extends Action ->trigger(); } - private function notifyDeleteExpiredSessions(Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_SESSIONS) - ->trigger(); - } - - private function renewCertificates(Database $dbForConsole, Certificate $queueForCertificate): void + private function renewCertificates(Database $dbForPlatform, Certificate $queueForCertificate): void { $time = DateTime::now(); - $certificates = $dbForConsole->find('certificates', [ + $certificates = $dbForPlatform->find('certificates', [ Query::lessThan('attempts', 5), // Maximum 5 attempts + Query::isNotNull('renewDate'), Query::lessThanEqual('renewDate', $time), // includes 60 days cooldown (we have 30 days to renew) Query::limit(200), // Limit 200 comes from LetsEncrypt (300 orders per 3 hours, keeping some for new domains) ]); @@ -184,11 +120,4 @@ class Maintenance extends Action ->setDatetime(DateTime::addSeconds(new \DateTime(), -1 * $interval)) ->trigger(); } - - private function notifyDeleteTargets(Delete $queueForDeletes): void - { - $queueForDeletes - ->setType(DELETE_TYPE_EXPIRED_TARGETS) - ->trigger(); - } } diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index dcba59bb1d..4bc640639f 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -30,14 +30,10 @@ class Migrate extends Action ->desc('Migrate Appwrite to new version') /** @TODO APP_VERSION_STABLE needs to be defined */ ->param('version', APP_VERSION_STABLE, new Text(8), 'Version to migrate to.', true) - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') ->inject('register') - ->callback(function ($version, $dbForConsole, $getProjectDB, Registry $register) { - \Co\run(function () use ($version, $dbForConsole, $getProjectDB, $register) { - $this->action($version, $dbForConsole, $getProjectDB, $register); - }); - }); + ->callback([$this, 'action']); } private function clearProjectsCache(Document $project) @@ -58,7 +54,7 @@ class Migrate extends Action } } - public function action(string $version, Database $dbForConsole, callable $getProjectDB, Registry $register) + public function action(string $version, Database $dbForPlatform, callable $getProjectDB, Registry $register) { Authorization::disable(); if (!array_key_exists($version, Migration::$versions)) { @@ -93,10 +89,10 @@ class Migrate extends Action $count = 0; try { - $totalProjects = $dbForConsole->count('projects') + 1; + $totalProjects = $dbForPlatform->count('projects') + 1; } catch (\Throwable $th) { - $dbForConsole->setNamespace('_console'); - $totalProjects = $dbForConsole->count('projects') + 1; + $dbForPlatform->setNamespace('_console'); + $totalProjects = $dbForPlatform->count('projects') + 1; } $class = 'Appwrite\\Migration\\Version\\' . Migration::$versions[$version]; @@ -120,7 +116,7 @@ class Migrate extends Action $projectDB = $getProjectDB($project); $projectDB->disableValidation(); $migration - ->setProject($project, $projectDB, $dbForConsole) + ->setProject($project, $projectDB, $dbForPlatform) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { @@ -132,7 +128,7 @@ class Migrate extends Action } $sum = \count($projects); - $projects = $dbForConsole->find('projects', [Query::limit($limit), Query::offset($offset)]); + $projects = $dbForPlatform->find('projects', [Query::limit($limit), Query::offset($offset)]); $offset = $offset + $limit; $count = $count + $sum; diff --git a/src/Appwrite/Platform/Tasks/QueueCount.php b/src/Appwrite/Platform/Tasks/QueueCount.php deleted file mode 100644 index b02165c1d2..0000000000 --- a/src/Appwrite/Platform/Tasks/QueueCount.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -namespace Appwrite\Platform\Tasks; - -use Utopia\CLI\Console; -use Utopia\Platform\Action; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; -use Utopia\Validator\Text; -use Utopia\Validator\WhiteList; - -class QueueCount extends Action -{ - public static function getName(): string - { - return 'queue-count'; - } - - - public function __construct() - { - $this - ->desc('Return the number of from a specific queue identified by the name parameter with a specific type') - ->param('name', '', new Text(100), 'Queue name') - ->param('type', '', new WhiteList([ - 'success', - 'failed', - 'processing', - ]), 'Queue type') - ->inject('queue') - ->callback(fn ($name, $type, $queue) => $this->action($name, $type, $queue)); - } - - /** - * @param string $name The name of the queue to count the jobs from - * @param string $type The type of jobs to count - * @param Connection $queue - */ - public function action(string $name, string $type, Connection $queue): void - { - if (!$name) { - Console::error('Missing required parameter $name'); - return; - } - - $queueClient = new Client($name, $queue); - - $count = match ($type) { - 'success' => $queueClient->countSuccessfulJobs(), - 'failed' => $queueClient->countFailedJobs(), - 'processing' => $queueClient->countProcessingJobs(), - default => 0 - }; - - Console::log("Queue: '{$name}' has {$count} {$type} jobs."); - } -} diff --git a/src/Appwrite/Platform/Tasks/QueueRetry.php b/src/Appwrite/Platform/Tasks/QueueRetry.php index b6139dc177..f8099dcb00 100644 --- a/src/Appwrite/Platform/Tasks/QueueRetry.php +++ b/src/Appwrite/Platform/Tasks/QueueRetry.php @@ -4,8 +4,8 @@ namespace Appwrite\Platform\Tasks; use Utopia\CLI\Console; use Utopia\Platform\Action; -use Utopia\Queue\Client; -use Utopia\Queue\Connection; +use Utopia\Queue\Publisher; +use Utopia\Queue\Queue; use Utopia\Validator\Text; use Utopia\Validator\Wildcard; @@ -23,33 +23,24 @@ class QueueRetry extends Action ->desc('Retry failed jobs from a specific queue identified by the name parameter') ->param('name', '', new Text(100), 'Queue name') ->param('limit', 0, new Wildcard(), 'jobs limit', true) - ->inject('queue') - ->callback(fn ($name, $limit, $queue) => $this->action($name, $limit, $queue)); + ->inject('publisher') + ->callback([$this, 'action']); } /** * @param string $name The name of the queue to retry jobs from * @param mixed $limit - * @param Connection $queue + * @param Publisher $publisher */ - public function action(string $name, mixed $limit, Connection $queue): void + public function action(string $name, mixed $limit, Publisher $publisher): void { - if (!$name) { Console::error('Missing required parameter $name'); return; } $limit = (int)$limit; - $queueClient = new Client($name, $queue); - - if ($queueClient->countFailedJobs() === 0) { - Console::error('No failed jobs found.'); - return; - } - Console::log('Retrying failed jobs...'); - - $queueClient->retry($limit); + $publisher->retry(new Queue($name), $limit); } } diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index 65d2f7717c..cf917ae96b 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -25,6 +25,9 @@ use Appwrite\Spec\Swagger2; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Platform\Action; +use Utopia\Validator\Nullable; +use Utopia\Validator\Text; +use Utopia\Validator\WhiteList; class SDKs extends Action { @@ -37,23 +40,35 @@ class SDKs extends Action { $this ->desc('Generate Appwrite SDKs') - ->callback(fn () => $this->action()); + ->param('platform', null, new Nullable(new Text(256)), 'Selected Platform', optional: true) + ->param('sdk', null, new Nullable(new Text(256)), 'Selected SDK', optional: true) + ->param('version', null, new Nullable(new Text(256)), 'Selected SDK', optional: true) + ->param('git', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we use git push?', optional: true) + ->param('production', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we push to production?', optional: true) + ->param('message', null, new Nullable(new Text(256)), 'Commit Message', optional: true) + ->callback([$this, 'action']); } - public function action(): void + public function action(?string $selectedPlatform, ?string $selectedSDK, ?string $version, ?string $git, ?string $production, ?string $message): void { - $platforms = Config::getParam('platforms'); - $selectedPlatform = Console::confirm('Choose Platform ("' . APP_PLATFORM_CLIENT . '", "' . APP_PLATFORM_SERVER . '", "' . APP_PLATFORM_CONSOLE . '" or "*" for all):'); - $selectedSDK = \strtolower(Console::confirm('Choose SDK ("*" for all):')); - $version = Console::confirm('Choose an Appwrite version'); - $git = (Console::confirm('Should we use git push? (yes/no)') == 'yes'); - $production = ($git) ? (Console::confirm('Type "Appwrite" to push code to production git repos') == 'Appwrite') : false; - $message = ($git) ? Console::confirm('Please enter your commit message:') : ''; + $selectedPlatform ??= Console::confirm('Choose Platform ("' . APP_PLATFORM_CLIENT . '", "' . APP_PLATFORM_SERVER . '", "' . APP_PLATFORM_CONSOLE . '" or "*" for all):'); + $selectedSDK ??= \strtolower(Console::confirm('Choose SDK ("*" for all):')); + $version ??= Console::confirm('Choose an Appwrite version'); - 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', 'latest'])) { + $git ??= Console::confirm('Should we use git push? (yes/no)'); + $git = $git === 'yes'; + + if ($git) { + $production ??= Console::confirm('Type "Appwrite" to push code to production git repos'); + $production = $production === 'Appwrite'; + $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'])) { throw new \Exception('Unknown version given'); } + $platforms = Config::getParam('platforms'); foreach ($platforms as $key => $platform) { if ($selectedPlatform !== $key && $selectedPlatform !== '*') { continue; @@ -235,7 +250,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ->setTwitter(APP_SOCIAL_TWITTER_HANDLE) ->setDiscord(APP_SOCIAL_DISCORD_CHANNEL, APP_SOCIAL_DISCORD) ->setDefaultHeaders([ - 'X-Appwrite-Response-Format' => '1.6.0', + 'X-Appwrite-Response-Format' => '1.7.0', ]); // Make sure we have a clean slate. @@ -260,9 +275,13 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND \exec('rm -rf ' . $target . ' && \ mkdir -p ' . $target . ' && \ cd ' . $target . ' && \ - git init --initial-branch=' . $gitBranch . ' && \ + git init && \ git remote add origin ' . $gitUrl . ' && \ - git fetch origin ' . $gitBranch . ' && \ + git fetch origin && \ + git checkout main || git checkout -b main && \ + git pull origin main && \ + git checkout ' . $gitBranch . ' || git checkout -b ' . $gitBranch . ' && \ + git fetch origin ' . $gitBranch . ' || git push -u origin ' . $gitBranch . ' && \ git pull origin ' . $gitBranch . ' && \ rm -rf ' . $target . '/* && \ cp -r ' . $result . '/. ' . $target . '/ && \ diff --git a/src/Appwrite/Platform/Tasks/SSL.php b/src/Appwrite/Platform/Tasks/SSL.php index 5af0cb6cd8..ae1c93a360 100644 --- a/src/Appwrite/Platform/Tasks/SSL.php +++ b/src/Appwrite/Platform/Tasks/SSL.php @@ -24,7 +24,7 @@ class SSL extends Action ->param('domain', System::getEnv('_APP_DOMAIN', ''), new Hostname(), 'Domain to generate certificate for. If empty, main domain will be used.', true) ->param('skip-check', true, new Boolean(true), 'If DNS and renew check should be skipped. Defaults to true, and when true, all jobs will result in certificate generation attempt.', true) ->inject('queueForCertificates') - ->callback(fn (string $domain, bool|string $skipCheck, Certificate $queueForCertificates) => $this->action($domain, $skipCheck, $queueForCertificates)); + ->callback([$this, 'action']); } public function action(string $domain, bool|string $skipCheck, Certificate $queueForCertificates): void diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index a1b85c341f..303e03cb8c 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -9,6 +9,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Exception; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Pools\Group; use Utopia\System\System; @@ -25,7 +26,7 @@ abstract class ScheduleBase extends Action abstract public static function getName(): string; abstract public static function getSupportedResource(): string; abstract public static function getCollectionId(): string; - abstract protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void; + abstract protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void; public function __construct() { @@ -34,9 +35,20 @@ abstract class ScheduleBase extends Action $this ->desc("Execute {$type}s scheduled in Appwrite") ->inject('pools') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('getProjectDB') - ->callback(fn (Group $pools, Database $dbForConsole, callable $getProjectDB) => $this->action($pools, $dbForConsole, $getProjectDB)); + ->callback([$this, 'action']); + } + + protected function updateProjectAccess(Document $project, Database $dbForPlatform): void + { + if (!$project->isEmpty() && $project->getId() !== 'console') { + $accessedAt = $project->getAttribute('accessedAt', ''); + if (DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -APP_PROJECT_ACCESS)) > $accessedAt) { + $project->setAttribute('accessedAt', DateTime::now()); + Authorization::skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project)); + } + } } /** @@ -44,7 +56,7 @@ abstract class ScheduleBase extends Action * 2. Create timer that sync all changes from 'schedules' collection to local copy. Only reading changes thanks to 'resourceUpdatedAt' attribute * 3. Create timer that prepares coroutines for soon-to-execute schedules. When it's ready, coroutine sleeps until exact time before sending request to worker. */ - public function action(Group $pools, Database $dbForConsole, callable $getProjectDB): void + public function action(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { Console::title(\ucfirst(static::getSupportedResource()) . ' scheduler V1'); Console::success(APP_NAME . ' ' . \ucfirst(static::getSupportedResource()) . ' scheduler v1 has started'); @@ -56,8 +68,8 @@ abstract class ScheduleBase extends Action * @throws Exception * @var Document $schedule */ - $getSchedule = function (Document $schedule) use ($dbForConsole, $getProjectDB): array { - $project = $dbForConsole->getDocument('projects', $schedule->getAttribute('projectId')); + $getSchedule = function (Document $schedule) use ($dbForPlatform, $getProjectDB): array { + $project = $dbForPlatform->getDocument('projects', $schedule->getAttribute('projectId')); $resource = $getProjectDB($project)->getDocument( static::getCollectionId(), @@ -91,8 +103,15 @@ abstract class ScheduleBase extends Action $paginationQueries[] = Query::cursorAfter($latestDocument); } - $results = $dbForConsole->find('schedules', \array_merge($paginationQueries, [ - Query::equal('region', [System::getEnv('_APP_REGION', 'default')]), + // Temporarly accepting both 'fra' and 'default' + // When all migrated, only use _APP_REGION with 'default' as default value + $regions = [System::getEnv('_APP_REGION', 'default')]; + if (!in_array('default', $regions)) { + $regions[] = 'default'; + } + + $results = $dbForPlatform->find('schedules', \array_merge($paginationQueries, [ + Query::equal('region', $regions), Query::equal('resourceType', [static::getSupportedResource()]), Query::equal('active', [true]), ])); @@ -119,11 +138,11 @@ abstract class ScheduleBase extends Action Console::success("Starting timers at " . DateTime::now()); - run(function () use ($dbForConsole, &$lastSyncUpdate, $getSchedule, $pools, $getProjectDB) { + run(function () use ($dbForPlatform, &$lastSyncUpdate, $getSchedule, $pools, $getProjectDB) { /** * The timer synchronize $schedules copy with database collection. */ - Timer::tick(static::UPDATE_TIMER * 1000, function () use ($dbForConsole, &$lastSyncUpdate, $getSchedule, $pools) { + Timer::tick(static::UPDATE_TIMER * 1000, function () use ($dbForPlatform, &$lastSyncUpdate, $getSchedule, $pools) { $time = DateTime::now(); $timerStart = \microtime(true); @@ -141,8 +160,15 @@ abstract class ScheduleBase extends Action $paginationQueries[] = Query::cursorAfter($latestDocument); } - $results = $dbForConsole->find('schedules', \array_merge($paginationQueries, [ - Query::equal('region', [System::getEnv('_APP_REGION', 'default')]), + // Temporarly accepting both 'fra' and 'default' + // When all migrated, only use _APP_REGION with 'default' as default value + $regions = [System::getEnv('_APP_REGION', 'default')]; + if (!in_array('default', $regions)) { + $regions[] = 'default'; + } + + $results = $dbForPlatform->find('schedules', \array_merge($paginationQueries, [ + Query::equal('region', $regions), Query::equal('resourceType', [static::getSupportedResource()]), Query::greaterThanEqual('resourceUpdatedAt', $lastSyncUpdate), ])); @@ -179,10 +205,10 @@ abstract class ScheduleBase extends Action Timer::tick( static::ENQUEUE_TIMER * 1000, - fn () => $this->enqueueResources($pools, $dbForConsole, $getProjectDB) + fn () => $this->enqueueResources($pools, $dbForPlatform, $getProjectDB) ); - $this->enqueueResources($pools, $dbForConsole, $getProjectDB); + $this->enqueueResources($pools, $dbForPlatform, $getProjectDB); }); } } diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index 73a2814397..87f287f368 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -27,16 +27,16 @@ class ScheduleExecutions extends ScheduleBase return 'executions'; } - protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void + protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { - $queue = $pools->get('queue')->pop(); + $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) { if (!$schedule['active']) { - $dbForConsole->deleteDocument( + $dbForPlatform->deleteDocument( 'schedules', $schedule['$id'], ); @@ -50,20 +50,22 @@ class ScheduleExecutions extends ScheduleBase continue; } - $data = $dbForConsole->getDocument( + $data = $dbForPlatform->getDocument( 'schedules', $schedule['$id'], )->getAttribute('data', []); $delay = $scheduledAt->getTimestamp() - (new \DateTime())->getTimestamp(); + $this->updateProjectAccess($schedule['project'], $dbForPlatform); + \go(function () use ($queueForFunctions, $schedule, $delay, $data) { Co::sleep($delay); $queueForFunctions->setType('schedule') // Set functionId instead of function as we don't have $dbForProject // TODO: Refactor to use function instead of functionId - ->setFunctionId($schedule['resource']['functionId']) + ->setFunctionId($schedule['resource']['resourceId']) ->setExecution($schedule['resource']) ->setMethod($data['method'] ?? 'POST') ->setPath($data['path'] ?? '/') @@ -74,7 +76,7 @@ class ScheduleExecutions extends ScheduleBase ->trigger(); }); - $dbForConsole->deleteDocument( + $dbForPlatform->deleteDocument( 'schedules', $schedule['$id'], ); diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index 4d57902330..5b8e3027a7 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -31,7 +31,7 @@ class ScheduleFunctions extends ScheduleBase return 'functions'; } - protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void + protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { $timerStart = \microtime(true); $time = DateTime::now(); @@ -70,10 +70,10 @@ class ScheduleFunctions extends ScheduleBase } foreach ($delayedExecutions as $delay => $scheduleKeys) { - \go(function () use ($delay, $scheduleKeys, $pools) { + \go(function () use ($delay, $scheduleKeys, $pools, $dbForPlatform) { \sleep($delay); // in seconds - $queue = $pools->get('queue')->pop(); + $queue = $pools->get('publisher')->pop(); $connection = $queue->getResource(); foreach ($scheduleKeys as $scheduleKey) { @@ -84,6 +84,8 @@ class ScheduleFunctions extends ScheduleBase $schedule = $this->schedules[$scheduleKey]; + $this->updateProjectAccess($schedule['project'], $dbForPlatform); + $queueForFunctions = new Func($connection); $queueForFunctions diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index b9d8e2a282..201d5eab53 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -26,7 +26,7 @@ class ScheduleMessages extends ScheduleBase return 'messages'; } - protected function enqueueResources(Group $pools, Database $dbForConsole, callable $getProjectDB): void + protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { foreach ($this->schedules as $schedule) { if (!$schedule['active']) { @@ -40,18 +40,20 @@ class ScheduleMessages extends ScheduleBase continue; } - \go(function () use ($schedule, $pools, $dbForConsole) { - $queue = $pools->get('queue')->pop(); + \go(function () use ($schedule, $pools, $dbForPlatform) { + $queue = $pools->get('publisher')->pop(); $connection = $queue->getResource(); $queueForMessaging = new Messaging($connection); + $this->updateProjectAccess($schedule['project'], $dbForPlatform); + $queueForMessaging ->setType(MESSAGE_SEND_TYPE_EXTERNAL) ->setMessageId($schedule['resourceId']) ->setProject($schedule['project']) ->trigger(); - $dbForConsole->deleteDocument( + $dbForPlatform->deleteDocument( 'schedules', $schedule['$id'], ); diff --git a/src/Appwrite/Platform/Tasks/Screenshot.php b/src/Appwrite/Platform/Tasks/Screenshot.php new file mode 100644 index 0000000000..79593ab39b --- /dev/null +++ b/src/Appwrite/Platform/Tasks/Screenshot.php @@ -0,0 +1,308 @@ +<?php + +namespace Appwrite\Platform\Tasks; + +use Appwrite\ID; +use Tests\E2E\Client; +use Utopia\CLI\Console; +use Utopia\Config\Config; +use Utopia\Platform\Action; +use Utopia\Validator\Text; + +class Screenshot extends Action +{ + public static function getName(): string + { + return 'screenshot'; + } + + public function __construct() + { + $this + ->desc('Create Site template screenshot') + ->param('templateId', '', new Text(128), 'Template ID.') + ->callback([$this, 'action']); + } + + public function action(string $templateId): void + { + $templates = Config::getParam('templates-site', []); + + $allowedTemplates = \array_filter($templates, function ($item) use ($templateId) { + return $item['key'] === $templateId; + }); + $template = \array_shift($allowedTemplates); + + if (empty($template)) { + throw new \Exception("Template {$templateId} not found. Find correct ID in app/config/templates/site.php"); + } + + Console::info("Found: " . $template['name']); + + $client = new Client(); + $client->setEndpoint('http://localhost/v1'); + $client->addHeader('origin', 'http://localhost'); + + // Register + $email = uniqid() . 'user@localhost.test'; + $password = 'password'; + + Console::info("Email: {$email}"); + Console::info("Pass: {$password}"); + + $user = $client->call(Client::METHOD_POST, '/account', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + ], [ + 'userId' => ID::unique(), + 'email' => $email, + 'password' => $password, + ]); + + if ($user['headers']['status-code'] !== 201) { + Console::error(\json_encode($user)); + throw new \Exception("Failed to register user"); + } + + Console::info("User created"); + + // Login + $session = $client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + ], [ + 'email' => $email, + 'password' => $password, + ]); + + if ($session['headers']['status-code'] !== 201) { + Console::error(\json_encode($session)); + throw new \Exception("Failed to login user"); + } + + Console::info("Session created"); + + $secret = $session['cookies']['a_session_console']; + $cookieConsole = 'a_session_console=' . $secret; + + // Create organization + $team = $client->call(Client::METHOD_POST, '/teams', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + 'cookie' => $cookieConsole + ], [ + 'teamId' => ID::unique(), + 'name' => 'Demo Project Team', + ]); + + if ($team['headers']['status-code'] !== 201) { + Console::error(\json_encode($team)); + throw new \Exception("Failed to create team"); + } + + Console::info("Team created"); + + $projectName = 'Demo Project'; + $projectId = ID::unique(); + + // Create project + $project = $client->call(Client::METHOD_POST, '/projects', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + 'cookie' => $cookieConsole + ], [ + 'projectId' => $projectId, + 'region' => 'default', + 'name' => $projectName, + 'teamId' => $team['body']['$id'], + 'description' => 'Demo Project Description', + 'url' => 'https://appwrite.io', + ]); + + if ($project['headers']['status-code'] !== 201) { + Console::error(\json_encode($project)); + throw new \Exception("Failed to create project"); + } + + Console::info("Project created"); + + $projectId = $project['body']['$id']; + + $framework = $template['frameworks'][0]; + + // Create site + $site = $client->call(Client::METHOD_POST, '/sites', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-mode' => 'admin', + 'cookie' => $cookieConsole + ], [ + 'siteId' => ID::unique(), + 'name' => $template["name"], + 'framework' => $framework['key'], + 'adapter' => $framework['adapter'], + 'buildCommand' => $framework['buildCommand'] ?? '', + 'buildRuntime' => $framework['buildRuntime'], + 'fallbackFile' => $framework['fallbackFile'] ?? '', + 'installCommand' => $framework['installCommand'] ?? '', + 'outputDirectory' => $framework['outputDirectory'] ?? '', + 'providerRootDirectory' => $framework['providerRootDirectory'], + 'timeout' => 30 + ]); + + if ($site['headers']['status-code'] !== 201) { + Console::error(\json_encode($site)); + throw new \Exception("Failed to create site"); + } + + Console::info("Site created"); + + $siteId = $site['body']['$id']; + + // Create variables + if (!empty($template['variables'] ?? [])) { + foreach ($template['variables'] as $variable) { + if (empty($variable['value'] ?? '')) { + if (($variable['required'] ?? false) === true) { + throw new \Exception("Missing required variable: {$variable['name']}"); + } + + continue; + } + + $value = $variable['value']; + $value = \str_replace('{projectName}', $projectName, $value); + $value = \str_replace('{projectId}', $projectId, $value); + $value = \str_replace('{apiEndpoint}', 'http://localhost/v1', $value); + + $response = $client->call(Client::METHOD_POST, '/sites/' . $siteId . '/variables', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-mode' => 'admin', + 'cookie' => $cookieConsole + ], [ + 'key' => $variable['name'], + 'value' => $value + ]); + + if ($response['headers']['status-code'] !== 201) { + Console::error(\json_encode($response)); + throw new \Exception("Failed to create variable"); + } + } + + Console::info("Variables created"); + } + + // Create deployment + $deployment = $client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments/template', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-mode' => 'admin', + 'cookie' => $cookieConsole + ], [ + 'owner' => $template['providerOwner'], + 'repository' => $template['providerRepositoryId'], + 'rootDirectory' => $framework['providerRootDirectory'], + 'version' => $template['providerVersion'], + 'activate' => true, + ]); + + if ($deployment['headers']['status-code'] !== 202) { + Console::error(\json_encode($deployment)); + throw new \Exception("Failed to create deployment"); + } + + Console::info("Deployment created"); + + $deploymentId = $deployment['body']['$id']; + + // Await screenshot + $attempts = 60; // 5 min + $sleep = 5; + + $idLight = ''; + $idDark = ''; + + if ($templateId === 'starter-for-react-native') { + Console::warning("React Native template takes long to build, increasing waiting time ..."); + $attempts = 180; // 15 min + } + + Console::log("Awaiting deployment (every $sleep seconds, $attempts attempts)"); + + for ($i = 0; $i < $attempts; $i++) { + $deployment = $client->call(Client::METHOD_GET, '/sites/' . $siteId . '/deployments/' . $deploymentId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-mode' => 'admin', + 'cookie' => $cookieConsole + ]); + + if ($deployment['headers']['status-code'] !== 200) { + Console::error(\json_encode($deployment)); + throw new \Exception("Failed to get deployment"); + } + + if ($deployment['body']['status'] === 'failed') { + Console::error(\json_encode($deployment)); + throw new \Exception("Deployment build failed"); + } + + if ($deployment['body']['status'] !== 'ready') { + Console::log("Deployment not ready yet, status: " . $deployment['body']['status']); + \sleep($sleep); + continue; + } + + + if (empty($deployment['body']['screenshotLight'])) { + Console::log("Light screenshot not available yet"); + \sleep($sleep); + continue; + } + + if (empty($deployment['body']['screenshotDark'])) { + Console::log("Dark screenshot not available yet"); + \sleep($sleep); + continue; + } + + $idLight = $deployment['body']['screenshotLight']; + $idDark = $deployment['body']['screenshotDark']; + break; + } + + if (empty($idLight) || empty($idDark)) { + Console::error(\json_encode($deployment)); + throw new \Exception("Failed to get deployment screenshot"); + } + + Console::info("Screenshots created"); + + $themes = [ + [ 'fileId' => $idLight, 'suffix' => 'light' ], + [ 'fileId' => $idDark, 'suffix' => 'dark' ] + ]; + + foreach ($themes as $theme) { + $file = $client->call(Client::METHOD_GET, '/storage/buckets/screenshots/files/' . $theme['fileId'] . '/download', [ + 'x-appwrite-project' => 'console', + 'cookie' => $cookieConsole + ]); + + if ($file['headers']['status-code'] !== 200) { + Console::error(\json_encode($file)); + throw new \Exception("Failed to download {$theme['suffix']} screenshot"); + } + + $path = "/usr/src/code/public/images/sites/templates/{$template['key']}-{$theme['suffix']}.png"; + + if (!\file_put_contents($path, $file['body'])) { + throw new \Exception("Failed to save {$theme['suffix']} screenshot"); + } + } + + Console::success("Screenshots saved"); + } +} diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index f71de98d95..1db018ce9d 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Tasks; +use Appwrite\SDK\AuthType; use Appwrite\Specification\Format\OpenAPI3; use Appwrite\Specification\Format\Swagger2; use Appwrite\Specification\Specification; @@ -49,7 +50,7 @@ class Specs extends Action ->param('version', 'latest', new Text(16), 'Spec version', true) ->param('mode', 'normal', new WhiteList(['normal', 'mocks']), 'Spec Mode', true) ->inject('register') - ->callback(fn (string $version, string $mode, Registry $register) => $this->action($version, $mode, $register)); + ->callback([$this, 'action']); } public function action(string $version, string $mode, Registry $register): void @@ -61,7 +62,7 @@ class Specs extends Action // Mock dependencies App::setResource('request', fn () => $this->getRequest()); App::setResource('response', fn () => $response); - App::setResource('dbForConsole', fn () => new Database(new MySQL(''), new Cache(new None()))); + App::setResource('dbForPlatform', fn () => new Database(new MySQL(''), new Cache(new None()))); App::setResource('dbForProject', fn () => new Database(new MySQL(''), new Cache(new None()))); $platforms = [ @@ -182,56 +183,69 @@ class Specs extends Action foreach ($appRoutes as $key => $method) { foreach ($method as $route) { - $hide = $route->getLabel('sdk.hide', false); - if ($hide === true || (\is_array($hide) && \in_array($platform, $hide))) { + $sdks = $route->getLabel('sdk', false); + + if (empty($sdks)) { continue; } - /** @var \Utopia\Route $route */ - $routeSecurity = $route->getLabel('sdk.auth', []); - $sdkPlatforms = []; + if (!\is_array($sdks)) { + $sdks = [$sdks]; + } - foreach ($routeSecurity as $value) { - switch ($value) { - case APP_AUTH_TYPE_SESSION: - $sdkPlatforms[] = APP_PLATFORM_CLIENT; - break; - case APP_AUTH_TYPE_JWT: - case APP_AUTH_TYPE_KEY: - $sdkPlatforms[] = APP_PLATFORM_SERVER; - break; - case APP_AUTH_TYPE_ADMIN: - $sdkPlatforms[] = APP_PLATFORM_CONSOLE; - break; + foreach ($sdks as $sdk) { + /** @var \Appwrite\SDK\Method $sdks */ + + $hide = $sdk->isHidden(); + if ($hide === true || (\is_array($hide) && \in_array($platform, $hide))) { + continue; } - } - if (empty($routeSecurity)) { - $sdkPlatforms[] = APP_PLATFORM_SERVER; - $sdkPlatforms[] = APP_PLATFORM_CLIENT; - } + $routeSecurity = $sdk->getAuth(); + $sdkPlatforms = []; - if (!$route->getLabel('docs', true)) { - continue; - } + foreach ($routeSecurity as $value) { + switch ($value) { + case AuthType::SESSION: + $sdkPlatforms[] = APP_PLATFORM_CLIENT; + break; + case AuthType::JWT: + case AuthType::KEY: + $sdkPlatforms[] = APP_PLATFORM_SERVER; + break; + case AuthType::ADMIN: + $sdkPlatforms[] = APP_PLATFORM_CONSOLE; + break; + } + } - if ($route->getLabel('sdk.mock', false) && !$mocks) { - continue; - } + if (empty($routeSecurity)) { + $sdkPlatforms[] = APP_PLATFORM_SERVER; + $sdkPlatforms[] = APP_PLATFORM_CLIENT; + } - if (!$route->getLabel('sdk.mock', false) && $mocks) { - continue; - } + if (!$route->getLabel('docs', true)) { + continue; + } - if (empty($route->getLabel('sdk.namespace', null))) { - continue; - } + if ($route->getLabel('mock', false) && !$mocks) { + continue; + } - if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlatforms)) { - continue; - } + if (!$route->getLabel('mock', false) && $mocks) { + continue; + } - $routes[] = $route; + if (empty($sdk->getNamespace())) { + continue; + } + + if ($platform !== APP_PLATFORM_CONSOLE && !\in_array($platforms[$platform], $sdkPlatforms)) { + continue; + } + + $routes[] = $route; + } } } diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php new file mode 100644 index 0000000000..ac3b9ead73 --- /dev/null +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -0,0 +1,81 @@ +<?php + +namespace Appwrite\Platform\Tasks; + +use Appwrite\Event\StatsResources as EventStatsResources; +use Appwrite\Platform\Action; +use Utopia\CLI\Console; +use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; +use Utopia\System\System; + +/** + * Usage count + * + * Runs every hour, schedules project + * for aggregating resource count + */ +class StatsResources extends Action +{ + /** + * Log Error Callback + * + * @var callable + */ + protected mixed $logError; + + /** + * Console DB + * + * @var Database + */ + protected Database $dbForPlatform; + + public static function getName() + { + return 'stats-resources'; + } + + public function __construct() + { + $this + ->desc('Schedules projects for usage count') + ->inject('dbForPlatform') + ->inject('logError') + ->inject('queueForStatsResources') + ->callback([$this, 'action']); + } + + public function action(Database $dbForPlatform, callable $logError, EventStatsResources $queue): void + { + $this->logError = $logError; + $this->dbForPlatform = $dbForPlatform; + + Console::title("Stats resources V1"); + + Console::success('Stats resources: started'); + + $interval = (int) System::getEnv('_APP_STATS_RESOURCES_INTERVAL', '3600'); + Console::loop(function () use ($queue) { + Authorization::disable(); + Authorization::setDefaultStatus(false); + + $last24Hours = (new \DateTime())->sub(\DateInterval::createFromDateString('24 hours')); + /** + * For each project that were accessed in last 24 hours + */ + $this->foreachDocument($this->dbForPlatform, 'projects', [ + Query::greaterThanEqual('accessedAt', DateTime::format($last24Hours)) + ], function ($project) use ($queue) { + $queue + ->setProject($project) + ->trigger(); + Console::success('project: ' . $project->getId() . '(' . $project->getInternalId() . ')' . ' queued'); + }); + }, $interval); + + Console::log("Stats resources: exited"); + } +} diff --git a/src/Appwrite/Platform/Tasks/Upgrade.php b/src/Appwrite/Platform/Tasks/Upgrade.php index 341ce42fc4..dfd10d347e 100644 --- a/src/Appwrite/Platform/Tasks/Upgrade.php +++ b/src/Appwrite/Platform/Tasks/Upgrade.php @@ -23,7 +23,7 @@ class Upgrade extends Install ->param('image', 'appwrite', new Text(0), 'Main appwrite docker image', true) ->param('interactive', 'Y', new Text(1), 'Run an interactive session', true) ->param('no-start', false, new Boolean(true), 'Run an interactive session', true) - ->callback(fn ($httpPort, $httpsPort, $organization, $image, $interactive, $noStart) => $this->action($httpPort, $httpsPort, $organization, $image, $interactive, $noStart)); + ->callback([$this, 'action']); } public function action(string $httpPort, string $httpsPort, string $organization, string $image, string $interactive, bool $noStart): void diff --git a/src/Appwrite/Platform/Tasks/Vars.php b/src/Appwrite/Platform/Tasks/Vars.php index 499f8b15ec..70ae550ef9 100644 --- a/src/Appwrite/Platform/Tasks/Vars.php +++ b/src/Appwrite/Platform/Tasks/Vars.php @@ -18,7 +18,7 @@ class Vars extends Action { $this ->desc('List all the server environment variables') - ->callback(fn () => $this->action()); + ->callback([$this, 'action']); } public function action(): void diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 86ca59d3fd..76309145b8 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -2,18 +2,36 @@ namespace Appwrite\Platform\Workers; +use Appwrite\Auth\Auth; use Exception; use Throwable; use Utopia\Audit\Audit; -use Utopia\Database\Database; +use Utopia\CLI\Console; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Structure; use Utopia\Platform\Action; use Utopia\Queue\Message; +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 + + private int $lastTriggeredTime = 0; + + private array $logs = []; + + + protected function getBatchSize(): int + { + return System::getEnv('_APP_ENV', 'development') === 'development' + ? self::BATCH_SIZE_DEVELOPMENT + : self::BATCH_SIZE_PRODUCTION; + } + public static function getName(): string { return 'audits'; @@ -27,31 +45,40 @@ class Audits extends Action $this ->desc('Audits worker') ->inject('message') - ->inject('dbForProject') - ->callback(fn ($message, $dbForProject) => $this->action($message, $dbForProject)); + ->inject('getProjectDB') + ->inject('project') + ->callback([$this, 'action']); + + $this->lastTriggeredTime = time(); } /** * @param Message $message - * @param Database $dbForProject + * @param callable $getProjectDB + * @param Document $project * @return void * @throws Throwable * @throws \Utopia\Database\Exception * @throws Authorization * @throws Structure */ - public function action(Message $message, Database $dbForProject): void + public function action(Message $message, callable $getProjectDB, Document $project): void { - $payload = $message->getPayload() ?? []; if (empty($payload)) { throw new Exception('Missing payload'); } + Console::info('Aggregating audit logs'); + $event = $payload['event'] ?? ''; - $auditPayload = $payload['payload'] ?? ''; + + $auditPayload = ''; + if ($project->getId() === 'console') { + $auditPayload = $payload['payload'] ?? ''; + } $mode = $payload['mode'] ?? ''; $resource = $payload['resource'] ?? ''; $userAgent = $payload['userAgent'] ?? ''; @@ -60,23 +87,65 @@ class Audits extends Action $userName = $user->getAttribute('name', ''); $userEmail = $user->getAttribute('email', ''); + $userType = $user->getAttribute('type', Auth::ACTIVITY_TYPE_USER); - $audit = new Audit($dbForProject); - $audit->log( - userId: $user->getInternalId(), - // Pass first, most verbose event pattern - event: $event, - resource: $resource, - userAgent: $userAgent, - ip: $ip, - location: '', - data: [ + // Create event data + $eventData = [ + 'userId' => $user->getInternalId(), + 'event' => $event, + 'resource' => $resource, + 'userAgent' => $userAgent, + 'ip' => $ip, + 'location' => '', + 'data' => [ 'userId' => $user->getId(), 'userName' => $userName, 'userEmail' => $userEmail, + 'userType' => $userType, 'mode' => $mode, 'data' => $auditPayload, - ] - ); + ], + 'timestamp' => date("Y-m-d H:i:s", $message->getTimestamp()), + ]; + + if (isset($this->logs[$project->getInternalId()])) { + $this->logs[$project->getInternalId()]['logs'][] = $eventData; + } else { + $this->logs[$project->getInternalId()] = [ + 'project' => new Document([ + '$id' => $project->getId(), + '$internalId' => $project->getInternalId(), + 'database' => $project->getAttribute('database'), + ]), + 'logs' => [$eventData] + ]; + } + + // 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) { + $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(); + } + } } } diff --git a/src/Appwrite/Platform/Workers/Builds.php b/src/Appwrite/Platform/Workers/Builds.php deleted file mode 100644 index 5dd2f7f886..0000000000 --- a/src/Appwrite/Platform/Workers/Builds.php +++ /dev/null @@ -1,819 +0,0 @@ -<?php - -namespace Appwrite\Platform\Workers; - -use Ahc\Jwt\JWT; -use Appwrite\Event\Event; -use Appwrite\Event\Func; -use Appwrite\Event\Usage; -use Appwrite\Messaging\Adapter\Realtime; -use Appwrite\Utopia\Response\Model\Deployment; -use Appwrite\Vcs\Comment; -use Exception; -use Executor\Executor; -use Swoole\Coroutine as Co; -use Utopia\Cache\Cache; -use Utopia\CLI\Console; -use Utopia\Config\Config; -use Utopia\Database\Database; -use Utopia\Database\DateTime; -use Utopia\Database\Document; -use Utopia\Database\Exception\Conflict; -use Utopia\Database\Exception\Restricted; -use Utopia\Database\Exception\Structure; -use Utopia\Database\Helpers\ID; -use Utopia\Database\Validator\Authorization; -use Utopia\Logger\Log; -use Utopia\Platform\Action; -use Utopia\Queue\Message; -use Utopia\Storage\Device; -use Utopia\Storage\Device\Local; -use Utopia\System\System; -use Utopia\VCS\Adapter\Git\GitHub; - -class Builds extends Action -{ - public static function getName(): string - { - return 'builds'; - } - - /** - * @throws Exception - */ - public function __construct() - { - $this - ->desc('Builds worker') - ->inject('message') - ->inject('dbForConsole') - ->inject('queueForEvents') - ->inject('queueForFunctions') - ->inject('queueForUsage') - ->inject('cache') - ->inject('dbForProject') - ->inject('deviceForFunctions') - ->inject('log') - ->callback(fn ($message, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions, Usage $usage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log) => $this->action($message, $dbForConsole, $queueForEvents, $queueForFunctions, $usage, $cache, $dbForProject, $deviceForFunctions, $log)); - } - - /** - * @param Message $message - * @param Database $dbForConsole - * @param Event $queueForEvents - * @param Func $queueForFunctions - * @param Usage $queueForUsage - * @param Cache $cache - * @param Database $dbForProject - * @param Device $deviceForFunctions - * @param Log $log - * @return void - * @throws \Utopia\Database\Exception - */ - public function action(Message $message, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions, Usage $queueForUsage, Cache $cache, Database $dbForProject, Device $deviceForFunctions, Log $log): void - { - $payload = $message->getPayload() ?? []; - - if (empty($payload)) { - throw new \Exception('Missing payload'); - } - - $type = $payload['type'] ?? ''; - $project = new Document($payload['project'] ?? []); - $resource = new Document($payload['resource'] ?? []); - $deployment = new Document($payload['deployment'] ?? []); - $template = new Document($payload['template'] ?? []); - - $log->addTag('projectId', $project->getId()); - $log->addTag('type', $type); - - switch ($type) { - case BUILD_TYPE_DEPLOYMENT: - case BUILD_TYPE_RETRY: - Console::info('Creating build for deployment: ' . $deployment->getId()); - $github = new GitHub($cache); - $this->buildDeployment($deviceForFunctions, $queueForFunctions, $queueForEvents, $queueForUsage, $dbForConsole, $dbForProject, $github, $project, $resource, $deployment, $template, $log); - break; - - default: - throw new \Exception('Invalid build type'); - } - } - - /** - * @param Device $deviceForFunctions - * @param Func $queueForFunctions - * @param Event $queueForEvents - * @param Usage $queueForUsage - * @param Database $dbForConsole - * @param Database $dbForProject - * @param GitHub $github - * @param Document $project - * @param Document $function - * @param Document $deployment - * @param Document $template - * @param Log $log - * @return void - * @throws \Utopia\Database\Exception - * @throws Exception - */ - protected function buildDeployment(Device $deviceForFunctions, Func $queueForFunctions, Event $queueForEvents, Usage $queueForUsage, Database $dbForConsole, Database $dbForProject, GitHub $github, Document $project, Document $function, Document $deployment, Document $template, Log $log): void - { - $executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST')); - - $functionId = $function->getId(); - $log->addTag('functionId', $function->getId()); - - $function = $dbForProject->getDocument('functions', $functionId); - if ($function->isEmpty()) { - throw new \Exception('Function not found', 404); - } - - $deploymentId = $deployment->getId(); - $log->addTag('deploymentId', $deploymentId); - - $deployment = $dbForProject->getDocument('deployments', $deploymentId); - if ($deployment->isEmpty()) { - throw new \Exception('Deployment not found', 404); - } - - if (empty($deployment->getAttribute('entrypoint', ''))) { - throw new \Exception('Entrypoint for your Appwrite Function is missing. Please specify it when making deployment or update the entrypoint under your function\'s "Settings" > "Configuration" > "Entrypoint".', 500); - } - - $version = $function->getAttribute('version', 'v2'); - $spec = Config::getParam('runtime-specifications')[$function->getAttribute('specifications', APP_FUNCTION_SPECIFICATION_DEFAULT)]; - $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); - $key = $function->getAttribute('runtime'); - $runtime = $runtimes[$key] ?? null; - if (\is_null($runtime)) { - throw new \Exception('Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); - } - - // Realtime preparation - $allEvents = Event::generateEvents('functions.[functionId].deployments.[deploymentId].update', [ - 'functionId' => $function->getId(), - 'deploymentId' => $deployment->getId() - ]); - - $startTime = DateTime::now(); - $durationStart = \microtime(true); - $buildId = $deployment->getAttribute('buildId', ''); - $build = $dbForProject->getDocument('builds', $buildId); - $isNewBuild = empty($buildId); - if ($build->isEmpty()) { - $buildId = ID::unique(); - $build = $dbForProject->createDocument('builds', new Document([ - '$id' => $buildId, - '$permissions' => [], - 'startTime' => $startTime, - 'deploymentInternalId' => $deployment->getInternalId(), - 'deploymentId' => $deployment->getId(), - 'status' => 'processing', - 'path' => '', - 'runtime' => $function->getAttribute('runtime'), - 'source' => $deployment->getAttribute('path', ''), - 'sourceType' => strtolower($deviceForFunctions->getType()), - 'logs' => '', - 'endTime' => null, - 'duration' => 0, - 'size' => 0 - ])); - - $deployment->setAttribute('buildId', $build->getId()); - $deployment->setAttribute('buildInternalId', $build->getInternalId()); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - } elseif ($build->getAttribute('status') === 'canceled') { - Console::info('Build has been canceled'); - return; - } else { - $build = $dbForProject->getDocument('builds', $buildId); - } - - $source = $deployment->getAttribute('path', ''); - $installationId = $deployment->getAttribute('installationId', ''); - $providerRepositoryId = $deployment->getAttribute('providerRepositoryId', ''); - $providerCommitHash = $deployment->getAttribute('providerCommitHash', ''); - $isVcsEnabled = !empty($providerRepositoryId); - $owner = ''; - $repositoryName = ''; - - if ($isVcsEnabled) { - $installation = $dbForConsole->getDocument('installations', $installationId); - $providerInstallationId = $installation->getAttribute('providerInstallationId'); - $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); - $githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID'); - - $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); - } - - try { - if ($isNewBuild && !$isVcsEnabled) { - // Non-vcs+Template - - $templateRepositoryName = $template->getAttribute('repositoryName', ''); - $templateOwnerName = $template->getAttribute('ownerName', ''); - $templateVersion = $template->getAttribute('version', ''); - - $templateRootDirectory = $template->getAttribute('rootDirectory', ''); - $templateRootDirectory = \rtrim($templateRootDirectory, '/'); - $templateRootDirectory = \ltrim($templateRootDirectory, '.'); - $templateRootDirectory = \ltrim($templateRootDirectory, '/'); - - if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateVersion)) { - $stdout = ''; - $stderr = ''; - - // Clone template repo - $tmpTemplateDirectory = '/tmp/builds/' . $buildId . '-template'; - $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory); - $exit = Console::execute($gitCloneCommandForTemplate, '', $stdout, $stderr); - - if ($exit !== 0) { - throw new \Exception('Unable to clone code repository: ' . $stderr); - } - - // Ensure directories - Console::execute('mkdir -p ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory), '', $stdout, $stderr); - - $tmpPathFile = $tmpTemplateDirectory . '/code.tar.gz'; - - $localDevice = new Local(); - - if (substr($tmpTemplateDirectory, -1) !== '/') { - $tmpTemplateDirectory .= '/'; - } - - $tarParamDirectory = \escapeshellarg($tmpTemplateDirectory . (empty($templateRootDirectory) ? '' : '/' . $templateRootDirectory)); - Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellcmd($tarParamDirectory) . ' .', '', $stdout, $stderr); // TODO: Replace escapeshellcmd with escapeshellarg if we find a way that doesnt break syntax - - $source = $deviceForFunctions->getPath($deployment->getId() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); - $result = $localDevice->transfer($tmpPathFile, $source, $deviceForFunctions); - - if (!$result) { - throw new \Exception("Unable to move file"); - } - - Console::execute('rm -rf ' . \escapeshellarg($tmpTemplateDirectory), '', $stdout, $stderr); - - $directorySize = $deviceForFunctions->getFileSize($source); - $build = $dbForProject->updateDocument('builds', $build->getId(), $build->setAttribute('source', $source)); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttribute('path', $source)->setAttribute('size', $directorySize)); - } - } elseif ($isNewBuild && $isVcsEnabled) { - // VCS and VCS+Temaplte - $tmpDirectory = '/tmp/builds/' . $buildId . '/code'; - $rootDirectory = $function->getAttribute('providerRootDirectory', ''); - $rootDirectory = \rtrim($rootDirectory, '/'); - $rootDirectory = \ltrim($rootDirectory, '.'); - $rootDirectory = \ltrim($rootDirectory, '/'); - - $owner = $github->getOwnerName($providerInstallationId); - $repositoryName = $github->getRepositoryName($providerRepositoryId); - - $cloneOwner = $deployment->getAttribute('providerRepositoryOwner', $owner); - $cloneRepository = $deployment->getAttribute('providerRepositoryName', $repositoryName); - - $branchName = $deployment->getAttribute('providerBranch'); - $commitHash = $deployment->getAttribute('providerCommitHash', ''); - - $cloneVersion = $branchName; - $cloneType = GitHub::CLONE_TYPE_BRANCH; - if (!empty($commitHash)) { - $cloneVersion = $commitHash; - $cloneType = GitHub::CLONE_TYPE_COMMIT; - } - - $gitCloneCommand = $github->generateCloneCommand($cloneOwner, $cloneRepository, $cloneVersion, $cloneType, $tmpDirectory, $rootDirectory); - $stdout = ''; - $stderr = ''; - - Console::execute('mkdir -p ' . \escapeshellarg('/tmp/builds/' . $buildId), '', $stdout, $stderr); - - if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { - Console::info('Build has been canceled'); - return; - } - - $exit = Console::execute($gitCloneCommand, '', $stdout, $stderr); - - if ($exit !== 0) { - throw new \Exception('Unable to clone code repository: ' . $stderr); - } - - // Local refactoring for function folder with spaces - if (str_contains($rootDirectory, ' ')) { - $rootDirectoryWithoutSpaces = str_replace(' ', '', $rootDirectory); - $from = $tmpDirectory . '/' . $rootDirectory; - $to = $tmpDirectory . '/' . $rootDirectoryWithoutSpaces; - $exit = Console::execute('mv "' . \escapeshellarg($from) . '" "' . \escapeshellarg($to) . '"', '', $stdout, $stderr); - - if ($exit !== 0) { - throw new \Exception('Unable to move function with spaces' . $stderr); - } - $rootDirectory = $rootDirectoryWithoutSpaces; - } - - - // Build from template - $templateRepositoryName = $template->getAttribute('repositoryName', ''); - $templateOwnerName = $template->getAttribute('ownerName', ''); - $templateVersion = $template->getAttribute('version', ''); - - $templateRootDirectory = $template->getAttribute('rootDirectory', ''); - $templateRootDirectory = \rtrim($templateRootDirectory, '/'); - $templateRootDirectory = \ltrim($templateRootDirectory, '.'); - $templateRootDirectory = \ltrim($templateRootDirectory, '/'); - - if (!empty($templateRepositoryName) && !empty($templateOwnerName) && !empty($templateVersion)) { - // Clone template repo - $tmpTemplateDirectory = '/tmp/builds/' . $buildId . '/template'; - - $gitCloneCommandForTemplate = $github->generateCloneCommand($templateOwnerName, $templateRepositoryName, $templateVersion, GitHub::CLONE_TYPE_TAG, $tmpTemplateDirectory, $templateRootDirectory); - $exit = Console::execute($gitCloneCommandForTemplate, '', $stdout, $stderr); - - if ($exit !== 0) { - throw new \Exception('Unable to clone code repository: ' . $stderr); - } - - // Ensure directories - Console::execute('mkdir -p ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory), '', $stdout, $stderr); - Console::execute('mkdir -p ' . \escapeshellarg($tmpDirectory . '/' . $rootDirectory), '', $stdout, $stderr); - - // Merge template into user repo - Console::execute('rsync -av --exclude \'.git\' ' . \escapeshellarg($tmpTemplateDirectory . '/' . $templateRootDirectory . '/') . ' ' . \escapeshellarg($tmpDirectory . '/' . $rootDirectory), '', $stdout, $stderr); - - // Commit and push - $exit = Console::execute('git config --global user.email "team@appwrite.io" && git config --global user.name "Appwrite" && cd ' . \escapeshellarg($tmpDirectory) . ' && git add . && git commit -m "Create ' . \escapeshellarg($function->getAttribute('name', '')) . ' function" && git push origin ' . \escapeshellarg($branchName), '', $stdout, $stderr); - - if ($exit !== 0) { - throw new \Exception('Unable to push code repository: ' . $stderr); - } - - $exit = Console::execute('cd ' . \escapeshellarg($tmpDirectory) . ' && git rev-parse HEAD', '', $stdout, $stderr); - - if ($exit !== 0) { - throw new \Exception('Unable to get vcs commit SHA: ' . $stderr); - } - - $providerCommitHash = \trim($stdout); - $authorUrl = "https://github.com/$cloneOwner"; - - $deployment->setAttribute('providerCommitHash', $providerCommitHash ?? ''); - $deployment->setAttribute('providerCommitAuthorUrl', $authorUrl); - $deployment->setAttribute('providerCommitAuthor', 'Appwrite'); - $deployment->setAttribute('providerCommitMessage', "Create '" . $function->getAttribute('name', '') . "' function"); - $deployment->setAttribute('providerCommitUrl', "https://github.com/$cloneOwner/$cloneRepository/commit/$providerCommitHash"); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - - /** - * Send realtime Event - */ - $target = Realtime::fromPayload( - // Pass first, most verbose event pattern - event: $allEvents[0], - payload: $build, - project: $project - ); - Realtime::send( - projectId: 'console', - payload: $build->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'] - ); - } - - $tmpPath = '/tmp/builds/' . $buildId; - $tmpPathFile = $tmpPath . '/code.tar.gz'; - $localDevice = new Local(); - - if (substr($tmpDirectory, -1) !== '/') { - $tmpDirectory .= '/'; - } - - $directorySize = $localDevice->getDirectorySize($tmpDirectory); - $functionsSizeLimit = (int)System::getEnv('_APP_FUNCTIONS_SIZE_LIMIT', '30000000'); - if ($directorySize > $functionsSizeLimit) { - throw new \Exception('Repository directory size should be less than ' . number_format($functionsSizeLimit / 1048576, 2) . ' MBs.'); - } - - $tarParamDirectory = '/tmp/builds/' . $buildId . '/code' . (empty($rootDirectory) ? '' : '/' . $rootDirectory); - Console::execute('tar --exclude code.tar.gz -czf ' . \escapeshellarg($tmpPathFile) . ' -C ' . \escapeshellcmd($tarParamDirectory) . ' .', '', $stdout, $stderr); // TODO: Replace escapeshellcmd with escapeshellarg if we find a way that doesnt break syntax - - $source = $deviceForFunctions->getPath($deployment->getId() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); - $result = $localDevice->transfer($tmpPathFile, $source, $deviceForFunctions); - - if (!$result) { - throw new \Exception("Unable to move file"); - } - - Console::execute('rm -rf ' . \escapeshellarg($tmpPath), '', $stdout, $stderr); - - $build = $dbForProject->updateDocument('builds', $build->getId(), $build->setAttribute('source', $source)); - - $directorySize = $deviceForFunctions->getFileSize($source); - $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment->setAttribute('path', $source)->setAttribute('size', $directorySize)); - - $this->runGitAction('processing', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForConsole); - } - - /** Request the executor to build the code... */ - $build->setAttribute('status', 'building'); - $build = $dbForProject->updateDocument('builds', $buildId, $build); - - if ($isVcsEnabled) { - $this->runGitAction('building', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForConsole); - } - - /** Trigger Webhook */ - $deploymentModel = new Deployment(); - $deploymentUpdate = - $queueForEvents - ->setQueue(Event::WEBHOOK_QUEUE_NAME) - ->setClass(Event::WEBHOOK_CLASS_NAME) - ->setProject($project) - ->setEvent('functions.[functionId].deployments.[deploymentId].update') - ->setParam('functionId', $function->getId()) - ->setParam('deploymentId', $deployment->getId()) - ->setPayload($deployment->getArrayCopy(array_keys($deploymentModel->getRules()))); - - $deploymentUpdate->trigger(); - - /** Trigger Functions */ - $queueForFunctions - ->from($deploymentUpdate) - ->trigger(); - - /** Trigger Realtime */ - $target = Realtime::fromPayload( - // Pass first, most verbose event pattern - event: $allEvents[0], - payload: $build, - project: $project - ); - - Realtime::send( - projectId: 'console', - payload: $build->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'] - ); - - $vars = []; - - // Shared vars - foreach ($function->getAttribute('varsProject', []) as $var) { - $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); - } - - // Function vars - foreach ($function->getAttribute('vars', []) as $var) { - $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); - } - - $cpus = $spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT; - $memory = max($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT, 1024); // We have a minimum of 1024MB here because some runtimes can't compile with less memory than this. - - $jwtExpiry = (int)System::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); - $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $jwtExpiry, 0); - $apiKey = $jwtObj->encode([ - 'projectId' => $project->getId(), - 'scopes' => $function->getAttribute('scopes', []) - ]); - - $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_DOMAIN'); - $endpoint = $protocol . '://' . $hostname . "/v1"; - - // Appwrite vars - $vars = \array_merge($vars, [ - 'APPWRITE_FUNCTION_API_ENDPOINT' => $endpoint, - 'APPWRITE_FUNCTION_API_KEY' => API_KEY_DYNAMIC . '_' . $apiKey, - 'APPWRITE_FUNCTION_ID' => $function->getId(), - 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name'), - 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), - 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), - 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', - 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', - 'APPWRITE_FUNCTION_CPUS' => $cpus, - 'APPWRITE_FUNCTION_MEMORY' => $memory, - 'APPWRITE_VERSION' => APP_VERSION_STABLE, - 'APPWRITE_REGION' => $project->getAttribute('region'), - 'APPWRITE_DEPLOYMENT_TYPE' => $deployment->getAttribute('type', ''), - 'APPWRITE_VCS_REPOSITORY_ID' => $deployment->getAttribute('providerRepositoryId', ''), - 'APPWRITE_VCS_REPOSITORY_NAME' => $deployment->getAttribute('providerRepositoryName', ''), - 'APPWRITE_VCS_REPOSITORY_OWNER' => $deployment->getAttribute('providerRepositoryOwner', ''), - 'APPWRITE_VCS_REPOSITORY_URL' => $deployment->getAttribute('providerRepositoryUrl', ''), - 'APPWRITE_VCS_REPOSITORY_BRANCH' => $deployment->getAttribute('providerBranch', ''), - 'APPWRITE_VCS_REPOSITORY_BRANCH_URL' => $deployment->getAttribute('providerBranchUrl', ''), - 'APPWRITE_VCS_COMMIT_HASH' => $deployment->getAttribute('providerCommitHash', ''), - 'APPWRITE_VCS_COMMIT_MESSAGE' => $deployment->getAttribute('providerCommitMessage', ''), - 'APPWRITE_VCS_COMMIT_URL' => $deployment->getAttribute('providerCommitUrl', ''), - 'APPWRITE_VCS_COMMIT_AUTHOR_NAME' => $deployment->getAttribute('providerCommitAuthor', ''), - 'APPWRITE_VCS_COMMIT_AUTHOR_URL' => $deployment->getAttribute('providerCommitAuthorUrl', ''), - 'APPWRITE_VCS_ROOT_DIRECTORY' => $deployment->getAttribute('providerRootDirectory', ''), - ]); - - $command = $deployment->getAttribute('commands', ''); - - $response = null; - $err = null; - - if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { - Console::info('Build has been canceled'); - return; - } - - $isCanceled = false; - - Co::join([ - Co\go(function () use ($executor, &$response, $project, $deployment, $source, $function, $runtime, $vars, $command, $cpus, $memory, &$err) { - try { - $version = $function->getAttribute('version', 'v2'); - $command = $version === 'v2' ? 'tar -zxf /tmp/code.tar.gz -C /usr/code && cd /usr/local/src/ && ./build.sh' : 'tar -zxf /tmp/code.tar.gz -C /mnt/code && helpers/build.sh "' . \trim(\escapeshellarg($command), "\'") . '"'; - - $response = $executor->createRuntime( - deploymentId: $deployment->getId(), - projectId: $project->getId(), - source: $source, - image: $runtime['image'], - version: $version, - cpus: $cpus, - memory: $memory, - remove: true, - entrypoint: $deployment->getAttribute('entrypoint'), - destination: APP_STORAGE_BUILDS . "/app-{$project->getId()}", - variables: $vars, - command: $command - ); - } catch (\Throwable $error) { - $err = $error; - } - }), - Co\go(function () use ($executor, $project, $deployment, &$response, &$build, $dbForProject, $allEvents, &$err, &$isCanceled) { - try { - $executor->getLogs( - deploymentId: $deployment->getId(), - projectId: $project->getId(), - callback: function ($logs) use (&$response, &$err, &$build, $dbForProject, $allEvents, $project, &$isCanceled) { - if ($isCanceled) { - return; - } - - // If we have response or error from concurrent coroutine, we already have latest logs - if ($response === null && $err === null) { - $build = $dbForProject->getDocument('builds', $build->getId()); - - if ($build->isEmpty()) { - throw new \Exception('Build not found', 404); - } - - if ($build->getAttribute('status') === 'canceled') { - $isCanceled = true; - Console::info('Ignoring realtime logs because build has been canceled'); - return; - } - - $logs = \mb_substr($logs, 0, null, 'UTF-8'); // Get only valid UTF8 part - removes leftover half-multibytes causing SQL errors - - $build = $build->setAttribute('logs', $build->getAttribute('logs', '') . $logs); - $build = $dbForProject->updateDocument('builds', $build->getId(), $build); - - /** - * Send realtime Event - */ - $target = Realtime::fromPayload( - // Pass first, most verbose event pattern - event: $allEvents[0], - payload: $build, - project: $project - ); - Realtime::send( - projectId: 'console', - payload: $build->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'] - ); - } - } - ); - } catch (\Throwable $error) { - if (empty($err)) { - $err = $error; - } - } - }), - ]); - - if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { - Console::info('Build has been canceled'); - return; - } - - if ($err) { - throw $err; - } - - $endTime = DateTime::now(); - $durationEnd = \microtime(true); - - $buildSizeLimit = (int)System::getEnv('_APP_FUNCTIONS_BUILD_SIZE_LIMIT', '2000000000'); - if ($response['size'] > $buildSizeLimit) { - throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / 1048576, 2) . ' MBs.'); - } - - /** Update the build document */ - $build->setAttribute('startTime', DateTime::format((new \DateTime())->setTimestamp(floor($response['startTime'])))); - $build->setAttribute('endTime', $endTime); - $build->setAttribute('duration', \intval(\ceil($durationEnd - $durationStart))); - $build->setAttribute('status', 'ready'); - $build->setAttribute('path', $response['path']); - $build->setAttribute('size', $response['size']); - $build->setAttribute('logs', $response['output']); - - $build = $dbForProject->updateDocument('builds', $buildId, $build); - - if ($isVcsEnabled) { - $this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForConsole); - } - - Console::success("Build id: $buildId created"); - - /** Set auto deploy */ - if ($deployment->getAttribute('activate') === true) { - $function->setAttribute('deploymentInternalId', $deployment->getInternalId()); - $function->setAttribute('deployment', $deployment->getId()); - $function->setAttribute('live', true); - $function = $dbForProject->updateDocument('functions', $function->getId(), $function); - } - - if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { - Console::info('Build has been canceled'); - return; - } - - /** Update function schedule */ - - // Inform scheduler if function is still active - $schedule = $dbForConsole->getDocument('schedules', $function->getAttribute('scheduleId')); - $schedule - ->setAttribute('resourceUpdatedAt', DateTime::now()) - ->setAttribute('schedule', $function->getAttribute('schedule')) - ->setAttribute('active', !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment'))); - Authorization::skip(fn () => $dbForConsole->updateDocument('schedules', $schedule->getId(), $schedule)); - } catch (\Throwable $th) { - if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') { - Console::info('Build has been canceled'); - return; - } - - $endTime = DateTime::now(); - $durationEnd = \microtime(true); - $build->setAttribute('endTime', $endTime); - $build->setAttribute('duration', \intval(\ceil($durationEnd - $durationStart))); - $build->setAttribute('status', 'failed'); - $build->setAttribute('logs', $th->getMessage()); - - $build = $dbForProject->updateDocument('builds', $buildId, $build); - - if ($isVcsEnabled) { - $this->runGitAction('failed', $github, $providerCommitHash, $owner, $repositoryName, $project, $function, $deployment->getId(), $dbForProject, $dbForConsole); - } - } finally { - /** - * Send realtime Event - */ - $target = Realtime::fromPayload( - // Pass first, most verbose event pattern - event: $allEvents[0], - payload: $build, - project: $project - ); - Realtime::send( - projectId: 'console', - payload: $build->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'] - ); - - /** Trigger usage queue */ - if ($build->getAttribute('status') === 'ready') { - $queueForUsage - ->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); - } elseif ($build->getAttribute('status') === 'failed') { - $queueForUsage - ->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); - } - - $queueForUsage - ->addMetric(METRIC_BUILDS, 1) // per project - ->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))) - ->setProject($project) - ->trigger(); - } - } - - /** - * @param string $status - * @param GitHub $github - * @param string $providerCommitHash - * @param string $owner - * @param string $repositoryName - * @param Document $project - * @param Document $function - * @param string $deploymentId - * @param Database $dbForProject - * @param Database $dbForConsole - * @return void - * @throws Structure - * @throws \Utopia\Database\Exception - * @throws Authorization - * @throws Conflict - * @throws Restricted - */ - protected function runGitAction(string $status, GitHub $github, string $providerCommitHash, string $owner, string $repositoryName, Document $project, Document $function, string $deploymentId, Database $dbForProject, Database $dbForConsole): void - { - if ($function->getAttribute('providerSilentMode', false) === true) { - return; - } - - $deployment = $dbForProject->getDocument('deployments', $deploymentId); - $commentId = $deployment->getAttribute('providerCommentId', ''); - - if (!empty($providerCommitHash)) { - $message = match ($status) { - 'ready' => 'Build succeeded.', - 'failed' => 'Build failed.', - 'processing' => 'Building...', - default => $status - }; - - $state = match ($status) { - 'ready' => 'success', - 'failed' => 'failure', - 'processing' => 'pending', - default => $status - }; - - $functionName = $function->getAttribute('name'); - $projectName = $project->getAttribute('name'); - - $name = "{$functionName} ({$projectName})"; - - $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_DOMAIN'); - $functionId = $function->getId(); - $projectId = $project->getId(); - $providerTargetUrl = $protocol . '://' . $hostname . "/console/project-$projectId/functions/function-$functionId"; - - $github->updateCommitStatus($repositoryName, $providerCommitHash, $owner, $state, $message, $providerTargetUrl, $name); - } - - if (!empty($commentId)) { - $retries = 0; - - while (true) { - $retries++; - - try { - $dbForConsole->createDocument('vcsCommentLocks', new Document([ - '$id' => $commentId - ])); - break; - } catch (\Throwable $err) { - if ($retries >= 9) { - throw $err; - } - - \sleep(1); - } - } - - // Wrap in try/finally to ensure lock file gets deleted - try { - $comment = new Comment(); - $comment->parseComment($github->getComment($owner, $repositoryName, $commentId)); - $comment->addBuild($project, $function, $status, $deployment->getId(), ['type' => 'logs']); - $github->updateComment($owner, $repositoryName, $commentId, $comment->generateComment()); - } finally { - $dbForConsole->deleteDocument('vcsCommentLocks', $commentId); - } - } - } -} diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 21d967d9e1..15f9645bb0 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -2,16 +2,17 @@ namespace Appwrite\Platform\Workers; +use Appwrite\Certificates\Adapter as CertificatesAdapter; use Appwrite\Event\Event; use Appwrite\Event\Func; use Appwrite\Event\Mail; -use Appwrite\Messaging\Adapter\Realtime; -use Appwrite\Network\Validator\CNAME; +use Appwrite\Event\Realtime; +use Appwrite\Event\Webhook; +use Appwrite\Network\Validator\DNS; use Appwrite\Template\Template; use Appwrite\Utopia\Response\Model\Rule; use Exception; use Throwable; -use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -27,6 +28,8 @@ use Utopia\Logger\Log; use Utopia\Platform\Action; use Utopia\Queue\Message; use Utopia\System\System; +use Utopia\Validator\AnyOf; +use Utopia\Validator\IP; class Certificates extends Action { @@ -43,27 +46,42 @@ class Certificates extends Action $this ->desc('Certificates worker') ->inject('message') - ->inject('dbForConsole') + ->inject('dbForPlatform') ->inject('queueForMails') ->inject('queueForEvents') + ->inject('queueForWebhooks') ->inject('queueForFunctions') + ->inject('queueForRealtime') ->inject('log') - ->callback(fn (Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log) => $this->action($message, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log)); + ->inject('certificates') + ->callback([$this, 'action']); } /** * @param Message $message - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Mail $queueForMails * @param Event $queueForEvents + * @param Webhook $queueForWebhooks * @param Func $queueForFunctions + * @param Realtime $queueForRealtime * @param Log $log + * @param CertificatesAdapter $certificates * @return void * @throws Throwable * @throws \Utopia\Database\Exception */ - public function action(Message $message, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log): void - { + public function action( + Message $message, + Database $dbForPlatform, + Mail $queueForMails, + Event $queueForEvents, + Webhook $queueForWebhooks, + Func $queueForFunctions, + Realtime $queueForRealtime, + Log $log, + CertificatesAdapter $certificates + ): void { $payload = $message->getPayload() ?? []; if (empty($payload)) { @@ -76,33 +94,44 @@ class Certificates extends Action $log->addTag('domain', $domain->get()); - $this->execute($domain, $dbForConsole, $queueForMails, $queueForEvents, $queueForFunctions, $log, $skipRenewCheck); + $this->execute($domain, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck); } /** * @param Domain $domain - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Mail $queueForMails * @param Event $queueForEvents * @param Func $queueForFunctions + * @param Realtime $queueForRealtime + * @param CertificatesAdapter $certificates * @param bool $skipRenewCheck * @return void * @throws Throwable * @throws \Utopia\Database\Exception */ - private function execute(Domain $domain, Database $dbForConsole, Mail $queueForMails, Event $queueForEvents, Func $queueForFunctions, Log $log, bool $skipRenewCheck = false): void - { + private function execute( + Domain $domain, + Database $dbForPlatform, + Mail $queueForMails, + Event $queueForEvents, + Webhook $queueForWebhooks, + Func $queueForFunctions, + Realtime $queueForRealtime, + Log $log, + CertificatesAdapter $certificates, + bool $skipRenewCheck = false + ): void { /** * 1. Read arguments and validate domain * 2. Get main domain * 3. Validate CNAME DNS if parameter is not main domain (meaning it's custom domain) - * 4. Validate security email. Cannot be empty, required by LetsEncrypt - * 5. Validate renew date with certificate file, unless requested to skip by parameter - * 6. Issue a certificate using certbot CLI - * 7. Update 'log' attribute on certificate document with Certbot message - * 8. Create storage folder for certificate, if not ready already - * 9. Move certificates from Certbot location to our Storage - * 10. Create/Update our Storage with new Traefik config with new certificate paths + * 4. Validate renew date with certificate file, unless requested to skip by parameter + * 5. Issue a certificate using certbot CLI + * 6. Update 'log' attribute on certificate document with Certbot message + * 7. Create storage folder for certificate, if not ready already + * 8. Move certificates from Certbot location to our Storage + * 9. Create/Update our Storage with new Traefik config with new certificate paths * 11. Read certificate file and update 'renewDate' on certificate document * 12. Update 'issueDate' and 'attempts' on certificate * @@ -119,11 +148,11 @@ class Certificates extends Action * 2. Save document to database * 3. Update all domains documents with current certificate ID * - * Note: Renewals are checked and scheduled from maintenence worker + * Note: Renewals are checked and scheduled from maintenance worker */ // Get current certificate - $certificate = $dbForConsole->findOne('certificates', [Query::equal('domain', [$domain->get()])]); + $certificate = $dbForPlatform->findOne('certificates', [Query::equal('domain', [$domain->get()])]); // If we don't have certificate for domain yet, let's create new document. At the end we save it if ($certificate->isEmpty()) { @@ -134,40 +163,28 @@ class Certificates extends Action $success = false; try { - // Email for alerts is required by LetsEncrypt - $email = System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS')); - if (empty($email)) { - throw new Exception('You must set a valid security email address (_APP_EMAIL_CERTIFICATES) to issue an SSL certificate.'); - } - // Validate domain and DNS records. Skip if job is forced if (!$skipRenewCheck) { $mainDomain = $this->getMainDomain(); $isMainDomain = !isset($mainDomain) || $domain->get() === $mainDomain; $this->validateDomain($domain, $isMainDomain, $log); + + // If certificate exists already, double-check expiry date. Skip if job is forced + if (!$certificates->isRenewRequired($domain->get(), $log)) { + Console::info("Skipping, renew isn't required"); + return; + } } - // If certificate exists already, double-check expiry date. Skip if job is forced - if (!$skipRenewCheck && !$this->isRenewRequired($domain->get(), $log)) { - throw new Exception('Renew isn\'t required.'); - } - - // Prepare folder name for certbot. Using this helps prevent miss-match in LetsEncrypt configuration when renewing certificate - $folder = ID::unique(); - - // Generate certificate files using Let's Encrypt - $letsEncryptData = $this->issueCertificate($folder, $domain->get(), $email); + // Prepare unique cert name. Using this helps prevent miss-match in configuration when renewing certificates. + $certName = ID::unique(); + $renewDate = $certificates->issueCertificate($certName, $domain->get()); // Command succeeded, store all data into document - $logs = 'Certificate successfully generated.'; - $certificate->setAttribute('logs', \mb_strcut($logs, 0, 1000000));// Limit to 1MB - - - // Give certificates to Traefik - $this->applyCertificateFiles($folder, $domain->get(), $letsEncryptData); + $certificate->setAttribute('logs', 'Certificate successfully generated.'); // Update certificate info stored in database - $certificate->setAttribute('renewDate', $this->getRenewDate($domain->get())); + $certificate->setAttribute('renewDate', $renewDate); $certificate->setAttribute('attempts', 0); $certificate->setAttribute('issueDate', DateTime::now()); $success = true; @@ -181,7 +198,7 @@ class Certificates extends Action $attempts = $certificate->getAttribute('attempts', 0) + 1; $certificate->setAttribute('attempts', $attempts); - // Store cuttent time as renew date to ensure another attempt in next maintenance cycle + // Store current time as renew date to ensure another attempt in next maintenance cycle. $certificate->setAttribute('renewDate', DateTime::now()); // Send email to security email @@ -193,7 +210,7 @@ class Certificates extends Action $certificate->setAttribute('updated', DateTime::now()); // Save all changes we made to certificate document into database - $this->saveCertificateDocument($domain->get(), $certificate, $success, $dbForConsole, $queueForEvents, $queueForFunctions); + $this->saveCertificateDocument($domain->get(), $certificate, $success, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime); } } @@ -203,30 +220,39 @@ class Certificates extends Action * @param string $domain Domain name that certificate is for * @param Document $certificate Certificate document that we need to save * @param bool $success - * @param Database $dbForConsole Database connection for console + * @param Database $dbForPlatform Database connection for console * @param Event $queueForEvents * @param Func $queueForFunctions + * @param Realtime $queueForRealtime * @return void * @throws \Utopia\Database\Exception * @throws Authorization * @throws Conflict * @throws Structure */ - private function saveCertificateDocument(string $domain, Document $certificate, bool $success, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions): void - { + private function saveCertificateDocument( + string $domain, + Document $certificate, + bool $success, + Database $dbForPlatform, + Event $queueForEvents, + Webhook $queueForWebhooks, + Func $queueForFunctions, + Realtime $queueForRealtime + ): void { // Check if update or insert required - $certificateDocument = $dbForConsole->findOne('certificates', [Query::equal('domain', [$domain])]); + $certificateDocument = $dbForPlatform->findOne('certificates', [Query::equal('domain', [$domain])]); if (!$certificateDocument->isEmpty()) { // Merge new data with current data $certificate = new Document(\array_merge($certificateDocument->getArrayCopy(), $certificate->getArrayCopy())); - $certificate = $dbForConsole->updateDocument('certificates', $certificate->getId(), $certificate); + $certificate = $dbForPlatform->updateDocument('certificates', $certificate->getId(), $certificate); } else { $certificate->removeAttribute('$internalId'); - $certificate = $dbForConsole->createDocument('certificates', $certificate); + $certificate = $dbForPlatform->createDocument('certificates', $certificate); } $certificateId = $certificate->getId(); - $this->updateDomainDocuments($certificateId, $domain, $success, $dbForConsole, $queueForEvents, $queueForFunctions); + $this->updateDomainDocuments($certificateId, $domain, $success, $dbForPlatform, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime); } /** @@ -245,8 +271,8 @@ class Certificates extends Action } /** - * Internal domain validation functionality to prevent unnecessary attempts failed from Let's Encrypt side. We check: - * - Domain needs to be public and valid (prevents NFT domains that are not supported by Let's Encrypt) + * Internal domain validation functionality to prevent unnecessary attempts. We check: + * - Domain needs to be public and valid (prevents NFT domains that are not supported) * - Domain must have proper DNS record * * @param Domain $domain Domain which we validate @@ -266,22 +292,39 @@ class Certificates extends Action } if (!$isMainDomain) { - // TODO: Would be awesome to also support A/AAAA records here. Maybe dry run? - // Validate if domain target is properly configured - $target = new Domain(System::getEnv('_APP_DOMAIN_TARGET', '')); + $validationStart = \microtime(true); - if (!$target->isKnown() || $target->isTest()) { - throw new Exception('Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.'); + $validators = []; + $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')); + 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); + } + if ((new IP(IP::V6))->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''))) { + $validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_AAAA', ''), DNS::RECORD_AAAA); + } + + // Validate if domain target is properly configured + if (empty($validators)) { + throw new Exception('At least one of domain targets environment variable must be configured.'); } // Verify domain with DNS records - $validationStart = \microtime(true); - $validator = new CNAME($target->get()); + $validator = new AnyOf($validators, AnyOf::TYPE_STRING); if (!$validator->isValid($domain->get())) { $log->addExtra('dnsTiming', \strval(\microtime(true) - $validationStart)); $log->addTag('dnsDomain', $domain->get()); - $error = $validator->getLogs(); + $errors = []; + foreach ($validators as $validator) { + if (!empty($validator->getLogs())) { + $errors[] = $validator->getLogs(); + } + } + + $error = \implode("\n", $errors); $log->addExtra('dnsResponse', \is_array($error) ? \json_encode($error) : \strval($error)); throw new Exception('Failed to verify domain DNS records.'); @@ -292,136 +335,6 @@ class Certificates extends Action } } - /** - * Reads expiry date of certificate from file and decides if renewal is required or not. - * - * @param string $domain Domain for which we check certificate file - * @return bool True, if certificate needs to be renewed - * @throws Exception - */ - private function isRenewRequired(string $domain, Log $log): bool - { - $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; - if (\file_exists($certPath)) { - $validTo = null; - - $certData = openssl_x509_parse(file_get_contents($certPath)); - $validTo = $certData['validTo_time_t'] ?? 0; - - if (empty($validTo)) { - $log->addTag('certificateDomain', $domain); - throw new Exception('Unable to read certificate file (cert.pem).'); - } - - // LetsEncrypt allows renewal 30 days before expiry - $expiryInAdvance = (60 * 60 * 24 * 30); - if ($validTo - $expiryInAdvance > \time()) { - $log->addTag('certificateDomain', $domain); - $log->addExtra('certificateData', \is_array($certData) ? \json_encode($certData) : \strval($certData)); - return false; - } - } - - return true; - } - - /** - * LetsEncrypt communication to issue certificate (using certbot CLI) - * - * @param string $folder Folder into which certificates should be generated - * @param string $domain Domain to generate certificate for - * @return array Named array with keys 'stdout' and 'stderr', both string - * @throws Exception - */ - private function issueCertificate(string $folder, string $domain, string $email): array - { - $stdout = ''; - $stderr = ''; - - $staging = (App::isProduction()) ? '' : ' --dry-run'; - $exit = Console::execute("certbot certonly -v --webroot --noninteractive --agree-tos{$staging}" - . " --email " . $email - . " --cert-name " . $folder - . " -w " . APP_STORAGE_CERTIFICATES - . " -d {$domain}", '', $stdout, $stderr); - - // Unexpected error, usually 5XX, API limits, ... - if ($exit !== 0) { - throw new Exception('Failed to issue a certificate with message: ' . $stderr); - } - - return [ - 'stdout' => $stdout, - 'stderr' => $stderr - ]; - } - - /** - * Read new renew date from certificate file generated by Let's Encrypt - * - * @param string $domain Domain which certificate was generated for - * @return string - * @throws \Utopia\Database\Exception - */ - private function getRenewDate(string $domain): string - { - $certPath = APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem'; - $certData = openssl_x509_parse(file_get_contents($certPath)); - $validTo = $certData['validTo_time_t'] ?? null; - $dt = (new \DateTime())->setTimestamp($validTo); - return DateTime::addSeconds($dt, -60 * 60 * 24 * 30); // -30 days - } - - /** - * Method to take files from Let's Encrypt, and put it into Traefik. - * - * @param string $domain Domain which certificate was generated for - * @param string $folder Folder in which certificates were generated - * @param array $letsEncryptData Let's Encrypt logs to use for additional info when throwing error - * @return void - * @throws Exception - */ - private function applyCertificateFiles(string $folder, string $domain, array $letsEncryptData): void - { - - // Prepare folder in storage for domain - $path = APP_STORAGE_CERTIFICATES . '/' . $domain; - if (!\is_readable($path)) { - if (!\mkdir($path, 0755, true)) { - throw new Exception('Failed to create path for certificate.'); - } - } - - // Move generated files - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/cert.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/cert.pem')) { - throw new Exception('Failed to rename certificate cert.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); - } - - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/chain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/chain.pem')) { - throw new Exception('Failed to rename certificate chain.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); - } - - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/fullchain.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/fullchain.pem')) { - throw new Exception('Failed to rename certificate fullchain.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); - } - - if (!@\rename('/etc/letsencrypt/live/' . $folder . '/privkey.pem', APP_STORAGE_CERTIFICATES . '/' . $domain . '/privkey.pem')) { - throw new Exception('Failed to rename certificate privkey.pem. Let\'s Encrypt log: ' . $letsEncryptData['stderr'] . ' ; ' . $letsEncryptData['stdout']); - } - - $config = \implode(PHP_EOL, [ - "tls:", - " certificates:", - " - certFile: /storage/certificates/{$domain}/fullchain.pem", - " keyFile: /storage/certificates/{$domain}/privkey.pem" - ]); - - // Save configuration into Traefik using our new cert files - if (!\file_put_contents(APP_STORAGE_CONFIG . '/' . $domain . '.yml', $config)) { - throw new Exception('Failed to save Traefik configuration.'); - } - } - /** * Method to make sure information about error is delivered to admnistrator. * @@ -475,15 +388,29 @@ class Certificates extends Action * * @return void */ - private function updateDomainDocuments(string $certificateId, string $domain, bool $success, Database $dbForConsole, Event $queueForEvents, Func $queueForFunctions): void - { - - $rule = $dbForConsole->getDocument('rules', md5($domain)); + private function updateDomainDocuments( + string $certificateId, + string $domain, + bool $success, + Database $dbForPlatform, + Event $queueForEvents, + Webhook $queueForWebhooks, + Func $queueForFunctions, + Realtime $queueForRealtime + ): void { + // TODO: @christyjacob remove once we migrate the rules in 1.7.x + if (System::getEnv('_APP_RULES_FORMAT') === 'md5') { + $rule = $dbForPlatform->getDocument('rules', md5($domain)); + } else { + $rule = $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$domain]), + ]); + } if (!$rule->isEmpty()) { $rule->setAttribute('certificateId', $certificateId); $rule->setAttribute('status', $success ? 'verified' : 'unverified'); - $dbForConsole->updateDocument('rules', $rule->getId(), $rule); + $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); $projectId = $rule->getAttribute('projectId'); @@ -492,50 +419,34 @@ class Certificates extends Action return; } - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + return; + } - /** Trigger Webhook */ $ruleModel = new Rule(); $queueForEvents ->setProject($project) ->setEvent('rules.[ruleId].update') ->setParam('ruleId', $rule->getId()) - ->setPayload($rule->getArrayCopy(array_keys($ruleModel->getRules()))) - ->trigger(); + ->setPayload($rule->getArrayCopy(array_keys($ruleModel->getRules()))); + /** Trigger Webhook */ + $queueForWebhooks + ->from($queueForEvents) + ->trigger(); /** Trigger Functions */ $queueForFunctions - ->setProject($project) - ->setEvent('rules.[ruleId].update') - ->setParam('ruleId', $rule->getId()) - ->setPayload($rule->getArrayCopy(array_keys($ruleModel->getRules()))) + ->from($queueForEvents) ->trigger(); - /** Trigger realtime event */ - $allEvents = Event::generateEvents('rules.[ruleId].update', [ - 'ruleId' => $rule->getId(), - ]); - $target = Realtime::fromPayload( - // Pass first, most verbose event pattern - event: $allEvents[0], - payload: $rule, - project: $project - ); - Realtime::send( - projectId: 'console', - payload: $rule->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'] - ); - Realtime::send( - projectId: $project->getId(), - payload: $rule->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'] - ); + /** Trigger Realtime Events */ + $queueForRealtime + ->from($queueForEvents) + ->setSubscribers(['console', $projectId]) + ->trigger(); } } } diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index fe81114ea0..91d4681340 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -2,8 +2,7 @@ namespace Appwrite\Platform\Workers; -use Appwrite\Event\Event; -use Appwrite\Messaging\Adapter\Realtime; +use Appwrite\Event\Realtime; use Exception; use Utopia\CLI\Console; use Utopia\Database\Database; @@ -11,6 +10,7 @@ use Utopia\Database\Document; use Utopia\Database\Exception as DatabaseException; use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; +use Utopia\Database\Exception\NotFound; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; @@ -33,30 +33,33 @@ class Databases extends Action $this ->desc('Databases worker') ->inject('message') - ->inject('dbForConsole') + ->inject('project') + ->inject('dbForPlatform') ->inject('dbForProject') + ->inject('queueForRealtime') ->inject('log') - ->callback(fn (Message $message, Database $dbForConsole, Database $dbForProject, Log $log) => $this->action($message, $dbForConsole, $dbForProject, $log)); + ->callback([$this, 'action']); } /** * @param Message $message - * @param Database $dbForConsole + * @param Document $project + * @param Database $dbForPlatform * @param Database $dbForProject + * @param Realtime $queueForRealtime * @param Log $log * @return void * @throws \Exception */ - public function action(Message $message, Database $dbForConsole, Database $dbForProject, Log $log): void + public function action(Message $message, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime, Log $log): void { $payload = $message->getPayload() ?? []; if (empty($payload)) { - throw new \Exception('Missing payload'); + throw new Exception('Missing payload'); } $type = $payload['type']; - $project = new Document($payload['project']); $collection = new Document($payload['collection'] ?? []); $document = new Document($payload['document'] ?? []); $database = new Document($payload['database'] ?? []); @@ -73,11 +76,11 @@ class Databases extends Action match (\strval($type)) { DATABASE_TYPE_DELETE_DATABASE => $this->deleteDatabase($database, $project, $dbForProject), DATABASE_TYPE_DELETE_COLLECTION => $this->deleteCollection($database, $collection, $project, $dbForProject), - DATABASE_TYPE_CREATE_ATTRIBUTE => $this->createAttribute($database, $collection, $document, $project, $dbForConsole, $dbForProject), - DATABASE_TYPE_DELETE_ATTRIBUTE => $this->deleteAttribute($database, $collection, $document, $project, $dbForConsole, $dbForProject), - DATABASE_TYPE_CREATE_INDEX => $this->createIndex($database, $collection, $document, $project, $dbForConsole, $dbForProject), - DATABASE_TYPE_DELETE_INDEX => $this->deleteIndex($database, $collection, $document, $project, $dbForConsole, $dbForProject), - default => throw new \Exception('No database operation for type: ' . \strval($type)), + DATABASE_TYPE_CREATE_ATTRIBUTE => $this->createAttribute($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_DELETE_ATTRIBUTE => $this->deleteAttribute($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_CREATE_INDEX => $this->createIndex($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + DATABASE_TYPE_DELETE_INDEX => $this->deleteIndex($database, $collection, $document, $project, $dbForPlatform, $dbForProject, $queueForRealtime), + default => throw new Exception('No database operation for type: ' . \strval($type)), }; } @@ -86,16 +89,24 @@ class Databases extends Action * @param Document $collection * @param Document $attribute * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Database $dbForProject + * @param Realtime $queueForRealtime * @return void * @throws Authorization * @throws Conflict * @throws \Exception * @throws \Throwable */ - private function createAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForConsole, Database $dbForProject): void - { + private function createAttribute( + Document $database, + Document $collection, + Document $attribute, + Document $project, + Database $dbForPlatform, + Database $dbForProject, + Realtime $queueForRealtime + ): void { if ($collection->isEmpty()) { throw new Exception('Missing collection'); } @@ -104,12 +115,7 @@ class Databases extends Action } $projectId = $project->getId(); - - $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].attributes.[attributeId].update', [ - 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId(), - 'attributeId' => $attribute->getId() - ]); + $event = "databases.[databaseId].collections.[collectionId].attributes.[attributeId].update"; /** * TODO @christyjacob4 verify if this is still the case * Fetch attribute from the database, since with Resque float values are loosing informations. @@ -133,7 +139,10 @@ class Databases extends Action $formatOptions = $attribute->getAttribute('formatOptions', []); $filters = $attribute->getAttribute('filters', []); $options = $attribute->getAttribute('options', []); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); + + $relatedAttribute = new Document(); + $relatedCollection = new Document(); try { switch ($type) { @@ -164,7 +173,7 @@ class Databases extends Action break; default: 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'); + throw new Exception('Failed to create Attribute'); } } @@ -174,7 +183,7 @@ class Databases extends Action if ($e instanceof DatabaseException) { $attribute->setAttribute('error', $e->getMessage()); - if (isset($relatedAttribute)) { + if (! $relatedAttribute->isEmpty()) { $relatedAttribute->setAttribute('error', $e->getMessage()); } } @@ -185,7 +194,7 @@ class Databases extends Action $attribute->setAttribute('status', 'failed') ); - if (isset($relatedAttribute)) { + if (! $relatedAttribute->isEmpty()) { $dbForProject->updateDocument( 'attributes', $relatedAttribute->getId(), @@ -195,9 +204,9 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $collection, $attribute, $project, $projectId, $events); + $this->trigger($database, $collection, $project, $event, $queueForRealtime, $attribute); - if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { + if (! $relatedCollection->isEmpty()) { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } @@ -210,15 +219,16 @@ class Databases extends Action * @param Document $collection * @param Document $attribute * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Database $dbForProject + * @param Realtime $queueForRealtime * @return void * @throws Authorization * @throws Conflict * @throws \Exception * @throws \Throwable **/ - private function deleteAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForConsole, Database $dbForProject): void + private function deleteAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void { if ($collection->isEmpty()) { throw new Exception('Missing collection'); @@ -228,17 +238,11 @@ class Databases extends Action } $projectId = $project->getId(); - - $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete', [ - 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId(), - 'attributeId' => $attribute->getId() - ]); + $event = 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].delete'; $collectionId = $collection->getId(); $key = $attribute->getAttribute('key', ''); - $status = $attribute->getAttribute('status', ''); $type = $attribute->getAttribute('type', ''); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); $options = $attribute->getAttribute('options', []); $relatedAttribute = new Document(); $relatedCollection = new Document(); @@ -251,23 +255,21 @@ class Databases extends Action try { try { - if ($status !== 'failed') { - if ($type === Database::VAR_RELATIONSHIP) { - if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); - if ($relatedCollection->isEmpty()) { - throw new DatabaseException('Collection not found'); - } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + if ($type === Database::VAR_RELATIONSHIP) { + if ($options['twoWay']) { + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + if ($relatedCollection->isEmpty()) { + throw new DatabaseException('Collection not found'); } - - 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->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { - throw new DatabaseException('Failed to delete Attribute'); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); } + + 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->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + throw new DatabaseException('Failed to delete Attribute'); } $dbForProject->deleteDocument('attributes', $attribute->getId()); @@ -275,6 +277,16 @@ class Databases extends Action if (!$relatedAttribute->isEmpty()) { $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); } + + } catch (NotFound $e) { + Console::error($e->getMessage()); + + $dbForProject->deleteDocument('attributes', $attribute->getId()); + + if (!$relatedAttribute->isEmpty()) { + $dbForProject->deleteDocument('attributes', $relatedAttribute->getId()); + } + } catch (\Throwable $e) { Console::error($e->getMessage()); @@ -299,7 +311,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $collection, $attribute, $project, $projectId, $events); + $this->trigger($database, $collection, $project, $event, $queueForRealtime, $attribute); } // The underlying database removes/rebuilds indexes when attribute is removed @@ -345,7 +357,7 @@ class Databases extends Action } if ($exists) { // Delete the duplicate if created, else update in db - $this->deleteIndex($database, $collection, $index, $project, $dbForConsole, $dbForProject); + $this->deleteIndex($database, $collection, $index, $project, $dbForPlatform, $dbForProject, $queueForRealtime); } else { $dbForProject->updateDocument('indexes', $index->getId(), $index); } @@ -354,11 +366,9 @@ class Databases extends Action } } finally { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); - if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) { + if (! $relatedCollection->isEmpty()) { $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } } } @@ -368,8 +378,9 @@ class Databases extends Action * @param Document $collection * @param Document $index * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Database $dbForProject + * @param Realtime $queueForRealtime * @return void * @throws Authorization * @throws Conflict @@ -377,7 +388,7 @@ class Databases extends Action * @throws DatabaseException * @throws \Throwable */ - private function createIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForConsole, Database $dbForProject): void + private function createIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void { if ($collection->isEmpty()) { throw new Exception('Missing collection'); @@ -387,19 +398,14 @@ class Databases extends Action } $projectId = $project->getId(); - - $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].indexes.[indexId].update', [ - 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId(), - 'indexId' => $index->getId() - ]); + $event = 'databases.[databaseId].collections.[collectionId].indexes.[indexId].update'; $collectionId = $collection->getId(); $key = $index->getAttribute('key', ''); $type = $index->getAttribute('type', ''); $attributes = $index->getAttribute('attributes', []); $lengths = $index->getAttribute('lengths', []); $orders = $index->getAttribute('orders', []); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); try { if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { @@ -419,7 +425,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $collection, $index, $project, $projectId, $events); + $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } } @@ -429,8 +435,9 @@ class Databases extends Action * @param Document $collection * @param Document $index * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Database $dbForProject + * @param Realtime $queueForRealtime * @return void * @throws Authorization * @throws Conflict @@ -438,7 +445,7 @@ class Databases extends Action * @throws DatabaseException * @throws \Throwable */ - private function deleteIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForConsole, Database $dbForProject): void + private function deleteIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForPlatform, Database $dbForProject, Realtime $queueForRealtime): void { if ($collection->isEmpty()) { throw new Exception('Missing collection'); @@ -448,15 +455,10 @@ class Databases extends Action } $projectId = $project->getId(); - - $events = Event::generateEvents('databases.[databaseId].collections.[collectionId].indexes.[indexId].delete', [ - 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId(), - 'indexId' => $index->getId() - ]); + $event = 'databases.[databaseId].collections.[collectionId].indexes.[indexId].delete'; $key = $index->getAttribute('key'); $status = $index->getAttribute('status', ''); - $project = $dbForConsole->getDocument('projects', $projectId); + $project = $dbForPlatform->getDocument('projects', $projectId); try { if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { @@ -479,7 +481,7 @@ class Databases extends Action throw $e; } finally { - $this->trigger($database, $collection, $index, $project, $projectId, $events); + $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); } } @@ -521,9 +523,10 @@ class Databases extends Action $collectionId = $collection->getId(); $collectionInternalId = $collection->getInternalId(); - $databaseId = $database->getId(); $databaseInternalId = $database->getInternalId(); + $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId()); + /** * Related collections relating to current collection */ @@ -542,8 +545,6 @@ class Databases extends Action } ); - $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId()); - $this->deleteByGroup('attributes', [ Query::equal('databaseInternalId', [$databaseInternalId]), Query::equal('collectionInternalId', [$collectionInternalId]) @@ -557,75 +558,73 @@ class Databases extends Action /** - * @param string $collection collectionID + * @param string $collectionId * @param array $queries * @param Database $database * @param callable|null $callback * @return void * @throws Exception */ - protected function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void + protected function deleteByGroup(string $collectionId, array $queries, Database $database, callable $callback = null): void { - $count = 0; - $chunk = 0; - $limit = 50; - $sum = $limit; + $start = \microtime(true); - $executionStart = \microtime(true); + try { + $documents = $database->deleteDocuments($collectionId, $queries); + } catch (\Throwable $th) { + $tenant = $database->getSharedTables() ? 'Tenant:'.$database->getTenant() : ''; + Console::error("Failed to delete documents for collection:{$database->getNamespace()}_{$collectionId} {$tenant} :{$th->getMessage()}"); + return; + } - while ($sum === $limit) { - $chunk++; - - $results = $database->find($collection, \array_merge([Query::limit($limit)], $queries)); - - $sum = count($results); - - Console::info('Deleting chunk #' . $chunk . '. Found ' . $sum . ' documents'); - - foreach ($results as $document) { - if ($database->deleteDocument($document->getCollection(), $document->getId())) { - Console::success('Deleted document "' . $document->getId() . '" successfully'); - - if (\is_callable($callback)) { - $callback($document); - } - } else { - Console::warning('Failed to delete document: ' . $document->getId()); - } - $count++; + if (\is_callable($callback)) { + foreach ($documents as $document) { + $callback($document); } } - $executionEnd = \microtime(true); + $end = \microtime(true); + $count = \count($documents); - Console::info("Deleted {$count} document by group in " . ($executionEnd - $executionStart) . " seconds"); + Console::info("Deleted {$count} documents by group in " . ($end - $start) . " seconds"); } + /** + * @param Document $database + * @param Document $collection + * @param Document $project + * @param Realtime $queueForRealtime + * @param Document|null $attribute + * @param Document|null $index + * @return void + */ protected function trigger( Document $database, Document $collection, - Document $attribute, Document $project, - string $projectId, - array $events + string $event, + Realtime $queueForRealtime, + Document|null $attribute = null, + Document|null $index = null, ): void { - $target = Realtime::fromPayload( - // Pass first, most verbose event pattern - event: $events[0], - payload: $attribute, - project: $project, - ); - Realtime::send( - projectId: 'console', - payload: $attribute->getArrayCopy(), - events: $events, - channels: $target['channels'], - roles: $target['roles'], - options: [ - 'projectId' => $projectId, - 'databaseId' => $database->getId(), - 'collectionId' => $collection->getId() - ] - ); + $queueForRealtime + ->setProject($project) + ->setSubscribers(['console']) + ->setEvent($event) + ->setParam('databaseId', $database->getId()) + ->setParam('collectionId', $collection->getId()); + + if ($attribute !== null && !empty($attribute)) { + $queueForRealtime + ->setParam('attributeId', $attribute->getId()) + ->setPayload($attribute->getArrayCopy()); + } + if ($index !== null && !empty($index)) { + $queueForRealtime + ->setParam('indexId', $index->getId()) + ->setPayload($index->getArrayCopy()); + } + + $queueForRealtime->trigger(); } } diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 48e4014f1e..89e7a61b6c 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -3,11 +3,11 @@ namespace Appwrite\Platform\Workers; use Appwrite\Auth\Auth; +use Appwrite\Certificates\Adapter as CertificatesAdapter; use Appwrite\Extend\Exception; use Executor\Executor; use Throwable; -use Utopia\Abuse\Abuse; -use Utopia\Abuse\Adapters\Database\TimeLimit; +use Utopia\Abuse\Adapters\TimeLimit\Database as AbuseDatabase; use Utopia\Audit\Audit; use Utopia\Cache\Adapter\Filesystem; use Utopia\Cache\Cache; @@ -22,6 +22,7 @@ use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization as ValidatorAuthorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Action; @@ -31,6 +32,8 @@ use Utopia\System\System; class Deletes extends Action { + protected array $selects = ['$internalId', '$id', '$collection', '$permissions', '$updatedAt']; + public static function getName(): string { return 'deletes'; @@ -44,25 +47,44 @@ class Deletes extends Action $this ->desc('Deletes worker') ->inject('message') - ->inject('dbForConsole') + ->inject('project') + ->inject('dbForPlatform') ->inject('getProjectDB') + ->inject('getLogsDB') ->inject('deviceForFiles') ->inject('deviceForFunctions') + ->inject('deviceForSites') ->inject('deviceForBuilds') ->inject('deviceForCache') - ->inject('abuseRetention') + ->inject('certificates') + ->inject('executor') ->inject('executionRetention') ->inject('auditRetention') ->inject('log') - ->callback(fn ($message, $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log) => $this->action($message, $dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $abuseRetention, $executionRetention, $auditRetention, $log)); + ->callback([$this, 'action']); } /** * @throws Exception * @throws Throwable */ - public function action(Message $message, Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, string $abuseRetention, string $executionRetention, string $auditRetention, Log $log): void - { + public function action( + Message $message, + Document $project, + Database $dbForPlatform, + callable $getProjectDB, + callable $getLogsDB, + Device $deviceForFiles, + Device $deviceForFunctions, + Device $deviceForSites, + Device $deviceForBuilds, + Device $deviceForCache, + CertificatesAdapter $certificates, + Executor $executor, + string $executionRetention, + string $auditRetention, + Log $log + ): void { $payload = $message->getPayload() ?? []; if (empty($payload)) { @@ -75,7 +97,6 @@ class Deletes extends Action $resource = $payload['resource'] ?? null; $resourceType = $payload['resourceType'] ?? null; $document = new Document($payload['document'] ?? []); - $project = new Document($payload['project'] ?? []); $log->addTag('projectId', $project->getId()); $log->addTag('type', $type); @@ -84,13 +105,16 @@ class Deletes extends Action case DELETE_TYPE_DOCUMENT: switch ($document->getCollection()) { case DELETE_TYPE_PROJECTS: - $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $document); + $this->deleteProject($dbForPlatform, $getProjectDB, $deviceForFiles, $deviceForSites, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $document); + break; + case DELETE_TYPE_SITES: + $this->deleteSite($dbForPlatform, $getProjectDB, $deviceForSites, $deviceForBuilds, $deviceForFiles, $document, $certificates, $project); break; case DELETE_TYPE_FUNCTIONS: - $this->deleteFunction($dbForConsole, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $document, $project); + $this->deleteFunction($dbForPlatform, $getProjectDB, $deviceForFunctions, $deviceForBuilds, $certificates, $document, $project, $executor); break; case DELETE_TYPE_DEPLOYMENTS: - $this->deleteDeployment($getProjectDB, $deviceForFunctions, $deviceForBuilds, $document, $project); + $this->deleteDeployment($dbForPlatform, $getProjectDB, $deviceForFunctions, $deviceForSites, $deviceForBuilds, $deviceForFiles, $document, $certificates, $project, $executor); break; case DELETE_TYPE_USERS: $this->deleteUser($getProjectDB, $document, $project); @@ -99,10 +123,10 @@ class Deletes extends Action $this->deleteBucket($getProjectDB, $deviceForFiles, $document, $project); break; case DELETE_TYPE_INSTALLATIONS: - $this->deleteInstallation($dbForConsole, $getProjectDB, $document, $project); + $this->deleteInstallation($dbForPlatform, $getProjectDB, $document, $project); break; case DELETE_TYPE_RULES: - $this->deleteRule($dbForConsole, $document); + $this->deleteRule($dbForPlatform, $document, $certificates); break; default: Console::error('No lazy delete operation available for document of type: ' . $document->getCollection()); @@ -110,7 +134,7 @@ class Deletes extends Action } break; case DELETE_TYPE_TEAM_PROJECTS: - $this->deleteProjectsByTeam($dbForConsole, $getProjectDB, $document); + $this->deleteProjectsByTeam($dbForPlatform, $getProjectDB, $certificates, $document); break; case DELETE_TYPE_EXECUTIONS: $this->deleteExecutionLogs($project, $getProjectDB, $executionRetention); @@ -120,17 +144,14 @@ class Deletes extends Action $this->deleteAuditLogs($project, $getProjectDB, $auditRetention); } break; - case DELETE_TYPE_ABUSE: - $this->deleteAbuseLogs($project, $getProjectDB, $abuseRetention); - break; case DELETE_TYPE_REALTIME: - $this->deleteRealtimeUsage($dbForConsole, $datetime); + $this->deleteRealtimeUsage($dbForPlatform, $datetime); break; case DELETE_TYPE_SESSIONS: $this->deleteExpiredSessions($project, $getProjectDB); break; case DELETE_TYPE_USAGE: - $this->deleteUsageStats($project, $getProjectDB, $hourlyUsageRetentionDatetime); + $this->deleteUsageStats($project, $getProjectDB, $getLogsDB, $hourlyUsageRetentionDatetime); break; case DELETE_TYPE_CACHE_BY_RESOURCE: $this->deleteCacheByResource($project, $getProjectDB, $resource, $resourceType); @@ -139,7 +160,7 @@ class Deletes extends Action $this->deleteCacheByDate($project, $getProjectDB, $datetime); break; case DELETE_TYPE_SCHEDULES: - $this->deleteSchedules($dbForConsole, $getProjectDB, $datetime); + $this->deleteSchedules($dbForPlatform, $getProjectDB, $datetime); break; case DELETE_TYPE_TOPIC: $this->deleteTopic($project, $getProjectDB, $document); @@ -153,13 +174,20 @@ class Deletes extends Action case DELETE_TYPE_SESSION_TARGETS: $this->deleteSessionTargets($project, $getProjectDB, $document); break; + case DELETE_TYPE_MAINTENANCE: + $this->deleteExpiredTargets($project, $getProjectDB); + $this->deleteExecutionLogs($project, $getProjectDB, $executionRetention); + $this->deleteAuditLogs($project, $getProjectDB, $auditRetention); + $this->deleteUsageStats($project, $getProjectDB, $getLogsDB, $hourlyUsageRetentionDatetime); + $this->deleteExpiredSessions($project, $getProjectDB); + break; default: throw new \Exception('No delete operation for type: ' . \strval($type)); } } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @param string $datetime * @param Document|null $document @@ -170,34 +198,47 @@ class Deletes extends Action * @throws Structure * @throws DatabaseException */ - private function deleteSchedules(Database $dbForConsole, callable $getProjectDB, string $datetime): void + private function deleteSchedules(Database $dbForPlatform, callable $getProjectDB, string $datetime): void { + // Temporarly accepting both 'fra' and 'default' + // When all migrated, only use _APP_REGION with 'default' as default value + $regions = [System::getEnv('_APP_REGION', 'default')]; + if (!in_array('default', $regions)) { + $regions[] = 'default'; + } + $this->listByGroup( 'schedules', [ - Query::equal('region', [System::getEnv('_APP_REGION', 'default')]), + Query::equal('region', $regions), Query::lessThanEqual('resourceUpdatedAt', $datetime), Query::equal('active', [false]), ], - $dbForConsole, - function (Document $document) use ($dbForConsole, $getProjectDB) { - $project = $dbForConsole->getDocument('projects', $document->getAttribute('projectId')); + $dbForPlatform, + function (Document $document) use ($dbForPlatform, $getProjectDB) { + $project = $dbForPlatform->getDocument('projects', $document->getAttribute('projectId')); if ($project->isEmpty()) { - $dbForConsole->deleteDocument('schedules', $document->getId()); + $dbForPlatform->deleteDocument('schedules', $document->getId()); Console::success('Deleted schedule for deleted project ' . $document->getAttribute('projectId')); return; } $collectionId = match ($document->getAttribute('resourceType')) { 'function' => 'functions', + 'execution' => 'executions', 'message' => 'messages' }; - $resource = $getProjectDB($project)->getDocument( - $collectionId, - $document->getAttribute('resourceId') - ); + try { + $resource = $getProjectDB($project)->getDocument( + $collectionId, + $document->getAttribute('resourceId') + ); + } catch (Throwable $e) { + Console::error('Failed to get resource for schedule ' . $document->getId() . ' ' . $e->getMessage()); + return; + } $delete = true; @@ -205,10 +246,13 @@ class Deletes extends Action case 'function': $delete = $resource->isEmpty(); break; + case 'execution': + $delete = false; + break; } if ($delete) { - $dbForConsole->deleteDocument('schedules', $document->getId()); + $dbForPlatform->deleteDocument('schedules', $document->getId()); Console::success('Deleting schedule for ' . $document->getAttribute('resourceType') . ' ' . $document->getAttribute('resourceId')); } } @@ -231,7 +275,8 @@ class Deletes extends Action $this->deleteByGroup( 'subscribers', [ - Query::equal('topicInternalId', [$topic->getInternalId()]) + Query::equal('topicInternalId', [$topic->getInternalId()]), + Query::orderAsc(), ], $getProjectDB($project) ); @@ -252,7 +297,8 @@ class Deletes extends Action $this->deleteByGroup( 'subscribers', [ - Query::equal('targetInternalId', [$target->getInternalId()]) + Query::equal('targetInternalId', [$target->getInternalId()]), + Query::orderAsc(), ], $dbForProject, function (Document $subscriber) use ($dbForProject, $target) { @@ -264,7 +310,7 @@ class Deletes extends Action MESSAGE_TYPE_EMAIL => 'emailTotal', MESSAGE_TYPE_SMS => 'smsTotal', MESSAGE_TYPE_PUSH => 'pushTotal', - default => throw new Exception('Invalid target provider type'), + default => throw new Exception('Invalid target CertificatesAdapter type'), }; $dbForProject->decreaseDocumentAttribute( 'topics', @@ -289,7 +335,8 @@ class Deletes extends Action $this->deleteByGroup( 'targets', [ - Query::equal('expired', [true]) + Query::equal('expired', [true]), + Query::orderAsc(), ], $getProjectDB($project), function (Document $target) use ($getProjectDB, $project) { @@ -303,7 +350,8 @@ class Deletes extends Action $this->deleteByGroup( 'targets', [ - Query::equal('sessionInternalId', [$session->getInternalId()]) + Query::equal('sessionInternalId', [$session->getInternalId()]), + Query::orderAsc(), ], $getProjectDB($project), function (Document $target) use ($getProjectDB, $project) { @@ -330,14 +378,20 @@ class Deletes extends Action new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) ); - $query[] = Query::equal('resource', [$resource]); + $queries = [ + Query::equal('resource', [$resource]) + ]; + if (!empty($resourceType)) { - $query[] = Query::equal('resourceType', [$resourceType]); + $queries[] = Query::equal('resourceType', [$resourceType]); } + $queries[] = Query::select($this->selects); + $queries[] = Query::orderAsc(); + $this->deleteByGroup( 'cache', - $query, + $queries, $dbForProject, function (Document $document) use ($cache, $projectId) { $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); @@ -368,13 +422,16 @@ class Deletes extends Action new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId) ); - $query = [ + $queries = [ + Query::select([...$this->selects, 'accessedAt']), Query::lessThan('accessedAt', $datetime), + Query::orderDesc('accessedAt'), + Query::orderDesc(), ]; $this->deleteByGroup( 'cache', - $query, + $queries, $dbForProject, function (Document $document) use ($cache, $projectId) { $path = APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $projectId . DIRECTORY_SEPARATOR . $document->getId(); @@ -389,20 +446,41 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @param string $hourlyUsageRetentionDatetime * @return void * @throws Exception */ - private function deleteUsageStats(Document $project, callable $getProjectDB, string $hourlyUsageRetentionDatetime): void + private function deleteUsageStats(Document $project, callable $getProjectDB, callable $getLogsDB, string $hourlyUsageRetentionDatetime): void { + /** @var Database $dbForProject*/ $dbForProject = $getProjectDB($project); - // Delete Usage stats + + $selects = [...$this->selects, 'time']; + + // Delete Usage stats from projectDB $this->deleteByGroup('stats', [ - Query::lessThan('time', $hourlyUsageRetentionDatetime), + Query::select($selects), Query::equal('period', ['1h']), + Query::lessThan('time', $hourlyUsageRetentionDatetime), + Query::orderDesc('time'), + Query::orderDesc(), ], $dbForProject); + + if ($project->getId() !== 'console') { + /** @var Database $dbForLogs*/ + $dbForLogs = call_user_func($getLogsDB, $project); + + // Delete Usage stats from logsDB + $this->deleteByGroup('stats', [ + Query::select($selects), + Query::equal('period', ['1h']), + Query::lessThan('time', $hourlyUsageRetentionDatetime), + Query::orderDesc('time'), + Query::orderDesc(), + ], $dbForLogs); + } } /** @@ -421,7 +499,8 @@ class Deletes extends Action $this->deleteByGroup( 'memberships', [ - Query::equal('teamInternalId', [$teamInternalId]) + Query::equal('teamInternalId', [$teamInternalId]), + Query::orderAsc() ], $dbForProject, function (Document $membership) use ($dbForProject) { @@ -432,7 +511,7 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Document $document * @return void * @throws Authorization @@ -442,26 +521,27 @@ class Deletes extends Action * @throws Structure * @throws Exception */ - private function deleteProjectsByTeam(Database $dbForConsole, callable $getProjectDB, Document $document): void + private function deleteProjectsByTeam(Database $dbForPlatform, callable $getProjectDB, CertificatesAdapter $certificates, Document $document): void { - $projects = $dbForConsole->find('projects', [ + $projects = $dbForPlatform->find('projects', [ Query::equal('teamInternalId', [$document->getInternalId()]) ]); foreach ($projects as $project) { $deviceForFiles = getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId()); + $deviceForSites = getDevice(APP_STORAGE_SITES . '/app-' . $project->getId()); $deviceForFunctions = getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId()); $deviceForBuilds = getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); $deviceForCache = getDevice(APP_STORAGE_CACHE . '/app-' . $project->getId()); - $this->deleteProject($dbForConsole, $getProjectDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $project); - $dbForConsole->deleteDocument('projects', $project->getId()); + $this->deleteProject($dbForPlatform, $getProjectDB, $deviceForFiles, $deviceForSites, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $project); + $dbForPlatform->deleteDocument('projects', $project->getId()); } } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @param Device $deviceForFiles * @param Device $deviceForFunctions @@ -473,7 +553,7 @@ class Deletes extends Action * @throws Authorization * @throws DatabaseException */ - private function deleteProject(Database $dbForConsole, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, Document $document): void + 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(); $projectId = $document->getId(); @@ -490,34 +570,41 @@ class Deletes extends Action $projectCollectionIds = [ ...\array_keys(Config::getParam('collections', [])['projects']), Audit::COLLECTION, - TimeLimit::COLLECTION, + AbuseDatabase::COLLECTION, ]; $limit = \count($projectCollectionIds) + 25; + $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); + $sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', '')); + + $projectTables = !\in_array($dsn->getHost(), $sharedTables); + $sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1); + $sharedTablesV2 = !$projectTables && !$sharedTablesV1; + $sharedTables = $sharedTablesV1 || $sharedTablesV2; + while (true) { $collections = $dbForProject->listCollections($limit); foreach ($collections as $collection) { - if ($dsn->getHost() !== System::getEnv('_APP_DATABASE_SHARED_TABLES', '') || !\in_array($collection->getId(), $projectCollectionIds)) { - try { + try { + if ($projectTables || !\in_array($collection->getId(), $projectCollectionIds)) { $dbForProject->deleteCollection($collection->getId()); - } catch (Throwable $e) { - Console::error('Error deleting '.$collection->getId().' '.$e->getMessage()); - - /** - * Ignore junction tables; - */ - if (!preg_match('/^_\d+_\d+$/', $collection->getId())) { - throw $e; - } + } else { + $this->deleteByGroup( + $collection->getId(), + [ + Query::orderAsc() + ], + database: $dbForProject + ); } - } else { - $this->deleteByGroup($collection->getId(), [], database: $dbForProject); + } catch (Throwable $e) { + Console::error('Error deleting '.$collection->getId().' '.$e->getMessage()); } } - if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { + if ($sharedTables) { $collectionsIds = \array_map(fn ($collection) => $collection->getId(), $collections); if (empty(\array_diff($collectionsIds, $projectCollectionIds))) { @@ -530,55 +617,83 @@ class Deletes extends Action // Delete Platforms $this->deleteByGroup('platforms', [ - Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole); + Query::equal('projectInternalId', [$projectInternalId]), + Query::orderAsc() + ], $dbForPlatform); // Delete project and function rules $this->deleteByGroup('rules', [ - Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole, function (Document $document) use ($dbForConsole) { - $this->deleteRule($dbForConsole, $document); + Query::equal('projectInternalId', [$projectInternalId]), + Query::orderAsc() + ], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) { + $this->deleteRule($dbForPlatform, $document, $certificates); }); // Delete Keys $this->deleteByGroup('keys', [ - Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole); + Query::equal('projectInternalId', [$projectInternalId]), + Query::orderAsc() + ], $dbForPlatform); // Delete Webhooks $this->deleteByGroup('webhooks', [ - Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole); + Query::equal('projectInternalId', [$projectInternalId]), + Query::orderAsc() + ], $dbForPlatform); // Delete VCS Installations $this->deleteByGroup('installations', [ - Query::equal('projectInternalId', [$projectInternalId]) - ], $dbForConsole); + Query::equal('projectInternalId', [$projectInternalId]), + Query::orderAsc() + ], $dbForPlatform); // Delete VCS Repositories $this->deleteByGroup('repositories', [ Query::equal('projectInternalId', [$projectInternalId]), - ], $dbForConsole); + Query::orderAsc() + ], $dbForPlatform); // Delete VCS comments $this->deleteByGroup('vcsComments', [ Query::equal('projectInternalId', [$projectInternalId]), - ], $dbForConsole); + Query::orderAsc() + ], $dbForPlatform); - // Delete Schedules (No projectInternalId in this collection) + // Delete Schedules $this->deleteByGroup('schedules', [ Query::equal('projectId', [$projectId]), - ], $dbForConsole); + Query::orderAsc() + ], $dbForPlatform); // Delete metadata table - if ($dsn->getHost() !== System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { - $dbForProject->deleteCollection('_metadata'); - } else { - $this->deleteByGroup('_metadata', [], $dbForProject); + if ($projectTables) { + $dbForProject->deleteCollection(Database::METADATA); + } elseif ($sharedTablesV1) { + $this->deleteByGroup( + Database::METADATA, + [ + Query::orderAsc() + ], + $dbForProject + ); + } elseif ($sharedTablesV2) { + $queries = \array_map( + fn ($id) => Query::notEqual('$id', $id), + $projectCollectionIds + ); + + $queries[] = Query::orderAsc(); + + $this->deleteByGroup( + Database::METADATA, + $queries, + $dbForProject + ); } // Delete all storage directories $deviceForFiles->delete($deviceForFiles->getRoot(), true); + $deviceForSites->delete($deviceForSites->getRoot(), true); $deviceForFunctions->delete($deviceForFunctions->getRoot(), true); $deviceForBuilds->delete($deviceForBuilds->getRoot(), true); $deviceForCache->delete($deviceForCache->getRoot(), true); @@ -599,14 +714,16 @@ class Deletes extends Action // Delete all sessions of this user from the sessions table and update the sessions field of the user record $this->deleteByGroup('sessions', [ - Query::equal('userInternalId', [$userInternalId]) + Query::equal('userInternalId', [$userInternalId]), + Query::orderAsc() ], $dbForProject); $dbForProject->purgeCachedDocument('users', $userId); // Delete Memberships and decrement team membership counts $this->deleteByGroup('memberships', [ - Query::equal('userInternalId', [$userInternalId]) + Query::equal('userInternalId', [$userInternalId]), + Query::orderAsc() ], $dbForProject, function (Document $document) use ($dbForProject) { if ($document->getAttribute('confirm')) { // Count only confirmed members $teamId = $document->getAttribute('teamId'); @@ -619,19 +736,22 @@ class Deletes extends Action // Delete tokens $this->deleteByGroup('tokens', [ - Query::equal('userInternalId', [$userInternalId]) + Query::equal('userInternalId', [$userInternalId]), + Query::orderAsc() ], $dbForProject); // Delete identities $this->deleteByGroup('identities', [ - Query::equal('userInternalId', [$userInternalId]) + Query::equal('userInternalId', [$userInternalId]), + Query::orderAsc() ], $dbForProject); // Delete targets $this->deleteByGroup( 'targets', [ - Query::equal('userInternalId', [$userInternalId]) + Query::equal('userInternalId', [$userInternalId]), + Query::orderAsc() ], $dbForProject, function (Document $target) use ($getProjectDB, $project) { @@ -641,7 +761,7 @@ class Deletes extends Action } /** - * @param database $dbForConsole + * @param database $dbForPlatform * @param callable $getProjectDB * @param string $datetime * @return void @@ -650,14 +770,18 @@ class Deletes extends Action private function deleteExecutionLogs(Document $project, callable $getProjectDB, string $datetime): void { $dbForProject = $getProjectDB($project); + // Delete Executions $this->deleteByGroup('executions', [ - Query::lessThan('$createdAt', $datetime) + Query::select([...$this->selects, '$createdAt']), + Query::lessThan('$createdAt', $datetime), + Query::orderDesc('$createdAt'), + Query::orderDesc(), ], $dbForProject); } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @return void * @throws Exception|Throwable @@ -670,49 +794,33 @@ class Deletes extends Action // Delete Sessions $this->deleteByGroup('sessions', [ - Query::lessThan('$createdAt', $expired) + Query::select([...$this->selects, '$createdAt']), + Query::lessThan('$createdAt', $expired), + Query::orderDesc('$createdAt'), + Query::orderDesc(), ], $dbForProject); } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param string $datetime * @return void * @throws Exception */ - private function deleteRealtimeUsage(Database $dbForConsole, string $datetime): void + private function deleteRealtimeUsage(Database $dbForPlatform, string $datetime): void { // Delete Dead Realtime Logs $this->deleteByGroup('realtime', [ - Query::lessThan('timestamp', $datetime) - ], $dbForConsole); + Query::lessThan('timestamp', $datetime), + Query::orderDesc('timestamp'), + Query::orderAsc(), + ], $dbForPlatform); } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB - * @param string $datetime - * @return void - * @throws Exception - */ - private function deleteAbuseLogs(Document $project, callable $getProjectDB, string $abuseRetention): void - { - $projectId = $project->getId(); - $dbForProject = $getProjectDB($project); - $timeLimit = new TimeLimit("", 0, 1, $dbForProject); - $abuse = new Abuse($timeLimit); - - try { - $abuse->cleanup($abuseRetention); - } catch (DatabaseException $e) { - Console::error('Failed to delete abuse logs for project ' . $projectId . ': ' . $e->getMessage()); - } - } - - /** - * @param Database $dbForConsole - * @param callable $getProjectDB - * @param string $datetime + * @param string $auditRetention * @return void * @throws Exception */ @@ -720,25 +828,114 @@ class Deletes extends Action { $projectId = $project->getId(); $dbForProject = $getProjectDB($project); - $audit = new Audit($dbForProject); try { - $audit->cleanup($auditRetention); + $this->deleteByGroup(Audit::COLLECTION, [ + Query::select([...$this->selects, 'time']), + Query::lessThan('time', $auditRetention), + Query::orderDesc('time'), + Query::orderAsc(), + ], $dbForProject); } catch (DatabaseException $e) { Console::error('Failed to delete audit logs for project ' . $projectId . ': ' . $e->getMessage()); } } + /** + * @param callable $getProjectDB + * @param Device $deviceForSites + * @param Device $deviceForBuilds + * @param Document $document function document + * @param Document $project + * @return void + * @throws Exception + */ + private function deleteSite(Database $dbForPlatform, callable $getProjectDB, Device $deviceForSites, Device $deviceForBuilds, Device $deviceForFiles, Document $document, CertificatesAdapter $certificates, Document $project): void + { + $dbForProject = $getProjectDB($project); + $siteId = $document->getId(); + $siteInternalId = $document->getInternalId(); + + /** + * Delete rules for site + */ + Console::info("Deleting rules for site " . $siteId); + $this->deleteByGroup('rules', [ + Query::equal('type', ['deployment']), + Query::equal('deploymentResourceType', ['site']), + Query::equal('deploymentResourceInternalId', [$siteInternalId]), + Query::equal('projectInternalId', [$project->getInternalId()]) + ], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) { + $this->deleteRule($dbForPlatform, $document, $certificates); + }); + + /** + * Delete Variables + */ + Console::info("Deleting variables for site " . $siteId); + $this->deleteByGroup('variables', [ + Query::equal('resourceType', ['site']), + Query::equal('resourceInternalId', [$siteInternalId]) + ], $dbForProject); + + /** + * Delete Deployments + */ + Console::info("Deleting deployments for site " . $siteId); + $deploymentInternalIds = []; + $deploymentIds = []; + $this->deleteByGroup('deployments', [ + Query::equal('resourceInternalId', [$siteInternalId]), + Query::equal('resourceType', ['site']), + Query::orderAsc() + ], $dbForProject, function (Document $document) use ($project, $certificates, $deviceForSites, $deviceForBuilds, $deviceForFiles, $dbForPlatform, &$deploymentInternalIds) { + $deploymentInternalIds[] = $document->getInternalId(); + $deploymentIds[] = $document->getId(); + $this->deleteBuildFiles($deviceForBuilds, $document); + $this->deleteDeploymentFiles($deviceForSites, $document); + $this->deleteDeploymentScreenshots($deviceForFiles, $dbForPlatform, $document); + }); + + /** + * Delete Logs + */ + Console::info("Deleting logs for site " . $siteId); + $this->deleteByGroup('executions', [ + Query::select($this->selects), + Query::equal('resourceInternalId', [$siteInternalId]), + Query::equal('resourceType', ['sites']), + Query::orderAsc() + ], $dbForProject); + + /** + * Delete VCS Repositories and VCS Comments + */ + Console::info("Deleting VCS repositories and comments linked to site " . $siteId); + $this->deleteByGroup('repositories', [ + Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('resourceInternalId', [$siteInternalId]), + Query::equal('resourceType', ['site']), + ], $dbForPlatform, function (Document $document) use ($dbForPlatform) { + $providerRepositoryId = $document->getAttribute('providerRepositoryId', ''); + $projectInternalId = $document->getAttribute('projectInternalId', ''); + $this->deleteByGroup('vcsComments', [ + Query::equal('providerRepositoryId', [$providerRepositoryId]), + Query::equal('projectInternalId', [$projectInternalId]), + ], $dbForPlatform); + }); + } + /** * @param callable $getProjectDB * @param Device $deviceForFunctions * @param Device $deviceForBuilds * @param Document $document function document * @param Document $project + * @param Executor $executor * @return void * @throws Exception */ - private function deleteFunction(Database $dbForConsole, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, Document $document, Document $project): void + private function deleteFunction(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, CertificatesAdapter $certificates, Document $document, Document $project, Executor $executor): void { $projectId = $project->getId(); $dbForProject = $getProjectDB($project); @@ -750,11 +947,13 @@ class Deletes extends Action */ Console::info("Deleting rules for function " . $functionId); $this->deleteByGroup('rules', [ - Query::equal('resourceType', ['function']), - Query::equal('resourceInternalId', [$functionInternalId]), - Query::equal('projectInternalId', [$project->getInternalId()]) - ], $dbForConsole, function (Document $document) use ($project, $dbForConsole) { - $this->deleteRule($dbForConsole, $document); + Query::equal('type', ['deployment']), + Query::equal('deploymentResourceType', ['function']), + Query::equal('deploymentResourceInternalId', [$functionInternalId]), + Query::equal('projectInternalId', [$project->getInternalId()]), + Query::orderAsc() + ], $dbForPlatform, function (Document $document) use ($project, $dbForPlatform, $certificates) { + $this->deleteRule($dbForPlatform, $document, $certificates); }); /** @@ -762,8 +961,9 @@ class Deletes extends Action */ Console::info("Deleting variables for function " . $functionId); $this->deleteByGroup('variables', [ + Query::equal('resourceInternalId', [$functionInternalId]), Query::equal('resourceType', ['function']), - Query::equal('resourceInternalId', [$functionInternalId]) + Query::orderAsc() ], $dbForProject); /** @@ -773,31 +973,24 @@ class Deletes extends Action $deploymentInternalIds = []; $this->deleteByGroup('deployments', [ - Query::equal('resourceInternalId', [$functionInternalId]) - ], $dbForProject, function (Document $document) use ($deviceForFunctions, &$deploymentInternalIds) { + Query::equal('resourceInternalId', [$functionInternalId]), + Query::equal('resourceType', ['function']), + Query::orderAsc() + ], $dbForProject, function (Document $document) use ($dbForPlatform, $project, $certificates, $deviceForFunctions, $deviceForBuilds, &$deploymentInternalIds) { $deploymentInternalIds[] = $document->getInternalId(); $this->deleteDeploymentFiles($deviceForFunctions, $document); + $this->deleteBuildFiles($deviceForBuilds, $document); }); - /** - * Delete builds - */ - Console::info("Deleting builds for function " . $functionId); - - foreach ($deploymentInternalIds as $deploymentInternalId) { - $this->deleteByGroup('builds', [ - Query::equal('deploymentInternalId', [$deploymentInternalId]) - ], $dbForProject, function (Document $document) use ($deviceForBuilds) { - $this->deleteBuildFiles($deviceForBuilds, $document); - }); - } - /** * Delete Executions */ Console::info("Deleting executions for function " . $functionId); $this->deleteByGroup('executions', [ - Query::equal('functionInternalId', [$functionInternalId]) + Query::select($this->selects), + Query::equal('resourceInternalId', [$functionInternalId]), + Query::equal('resourceType', ['functions']), + Query::orderAsc() ], $dbForProject); /** @@ -808,20 +1001,70 @@ class Deletes extends Action Query::equal('projectInternalId', [$project->getInternalId()]), Query::equal('resourceInternalId', [$functionInternalId]), Query::equal('resourceType', ['function']), - ], $dbForConsole, function (Document $document) use ($dbForConsole) { + Query::orderAsc() + ], $dbForPlatform, function (Document $document) use ($dbForPlatform) { $providerRepositoryId = $document->getAttribute('providerRepositoryId', ''); $projectInternalId = $document->getAttribute('projectInternalId', ''); + $this->deleteByGroup('vcsComments', [ Query::equal('providerRepositoryId', [$providerRepositoryId]), Query::equal('projectInternalId', [$projectInternalId]), - ], $dbForConsole); + Query::orderAsc() + ], $dbForPlatform); }); /** * Request executor to delete all deployment containers */ Console::info("Requesting executor to delete all deployment containers for function " . $functionId); - $this->deleteRuntimes($getProjectDB, $document, $project); + $this->deleteRuntimes($getProjectDB, $document, $project, $executor); + } + + private function deleteDeploymentScreenshots(Device $deviceForFiles, Database $dbForPlatform, Document $deployment): void + { + $screenshotIds = []; + if (!empty($deployment->getAttribute('screenshotLight', ''))) { + $screenshotIds[] = $deployment->getAttribute('screenshotLight', ''); + } + if (!empty($deployment->getAttribute('screenshotDark', ''))) { + $screenshotIds[] = $deployment->getAttribute('screenshotDark', ''); + } + + if (empty($screenshotIds)) { + return; + } + Console::info("Deleting screenshots for deployment " . $deployment->getId()); + + $bucket = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')); + if ($bucket->isEmpty()) { + Console::error('Failed to get bucket for deployment screenshots'); + return; + } + + foreach ($screenshotIds as $id) { + $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getInternalId(), $id)); + + if ($file->isEmpty()) { + Console::error('Failed to get deployment screenshot: ' . $id); + continue; + } + + $path = $file->getAttribute('path', ''); + + try { + if ($deviceForFiles->delete($path, true)) { + Console::success('Deleted deployment screenshot: ' . $path); + } else { + Console::error('Failed to delete deployment screenshot: ' . $path); + } + } catch (\Throwable $th) { + Console::error('Failed to delete deployment screenshot: ' . $path); + Console::error('[Error] Type: ' . get_class($th)); + Console::error('[Error] Message: ' . $th->getMessage()); + Console::error('[Error] File: ' . $th->getFile()); + Console::error('[Error] Line: ' . $th->getLine()); + } + } } /** @@ -832,7 +1075,7 @@ class Deletes extends Action private function deleteDeploymentFiles(Device $device, Document $deployment): void { $deploymentId = $deployment->getId(); - $deploymentPath = $deployment->getAttribute('path', ''); + $deploymentPath = $deployment->getAttribute('sourcePath', ''); if (empty($deploymentPath)) { Console::info("No deployment files for deployment " . $deploymentId); @@ -847,7 +1090,7 @@ class Deletes extends Action } else { Console::error('Failed to delete deployment files: ' . $deploymentPath); } - } catch (\Throwable $th) { + } catch (Throwable $th) { Console::error('Failed to delete deployment files: ' . $deploymentPath); Console::error('[Error] Type: ' . get_class($th)); Console::error('[Error] Message: ' . $th->getMessage()); @@ -861,13 +1104,13 @@ class Deletes extends Action * @param Document $build * @return void */ - private function deleteBuildFiles(Device $device, Document $build): void + private function deleteBuildFiles(Device $device, Document $deployment): void { - $buildId = $build->getId(); - $buildPath = $build->getAttribute('path', ''); + $deploymentId = $deployment->getId(); + $buildPath = $deployment->getAttribute('buildPath', ''); if (empty($buildPath)) { - Console::info("No build files for build " . $buildId); + Console::info("No build files for deployment " . $deploymentId); return; } @@ -877,7 +1120,7 @@ class Deletes extends Action } else { Console::error('Failed to delete build files: ' . $buildPath); } - } catch (\Throwable $th) { + } catch (Throwable $th) { Console::error('Failed to delete deployment files: ' . $buildPath); Console::error('[Error] Type: ' . get_class($th)); Console::error('[Error] Message: ' . $th->getMessage()); @@ -889,13 +1132,15 @@ class Deletes extends Action /** * @param callable $getProjectDB * @param Device $deviceForFunctions + * @param Device $deviceForSites * @param Device $deviceForBuilds * @param Document $document * @param Document $project + * @param Executor $executor * @return void * @throws Exception */ - private function deleteDeployment(callable $getProjectDB, Device $deviceForFunctions, Device $deviceForBuilds, Document $document, Document $project): void + private function deleteDeployment(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFunctions, Device $deviceForSites, Device $deviceForBuilds, Device $deviceForFiles, Document $document, CertificatesAdapter $certificates, Document $project, Executor $executor): void { $projectId = $project->getId(); $dbForProject = $getProjectDB($project); @@ -905,85 +1150,80 @@ class Deletes extends Action /** * Delete deployment files */ - $this->deleteDeploymentFiles($deviceForFunctions, $document); + match ($document->getAttribute('resourceType')) { + 'functions' => $this->deleteDeploymentFiles($deviceForFunctions, $document), + 'sites' => $this->deleteDeploymentFiles($deviceForSites, $document), + default => throw new Exception('Invalid resource type') + }; /** - * Delete builds + * Delete deployment screenshots */ - Console::info("Deleting builds for deployment " . $deploymentId); + $this->deleteDeploymentScreenshots($deviceForFiles, $dbForPlatform, $document); - $this->deleteByGroup('builds', [ - Query::equal('deploymentInternalId', [$deploymentInternalId]) - ], $dbForProject, function (Document $document) use ($deviceForBuilds) { - $this->deleteBuildFiles($deviceForBuilds, $document); + /** + * Delete deployment build + */ + $this->deleteBuildFiles($deviceForBuilds, $document); + + /** + * Delete rules associated with the deployment + */ + Console::info("Deleting rules for deployment " . $deploymentId); + $this->deleteByGroup('rules', [ + Query::equal('trigger', ['deployment']), + Query::equal('type', ['deployment']), + Query::equal('deploymentInternalId', [$deploymentInternalId]), + Query::equal('projectInternalId', [$project->getInternalId()]) + ], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) { + $this->deleteRule($dbForPlatform, $document, $certificates); }); /** * Request executor to delete all deployment containers */ Console::info("Requesting executor to delete deployment container for deployment " . $deploymentId); - $this->deleteRuntimes($getProjectDB, $document, $project); - } - - /** - * @param Document $document to be deleted - * @param Database $database to delete it from - * @param callable|null $callback to perform after document is deleted - * @return void - */ - private function deleteById(Document $document, Database $database, callable $callback = null): void - { - if ($database->deleteDocument($document->getCollection(), $document->getId())) { - Console::success('Deleted document "' . $document->getId() . '" successfully'); - - if (is_callable($callback)) { - $callback($document); - } - } else { - Console::error('Failed to delete document: ' . $document->getId()); - } + $this->deleteRuntimes($getProjectDB, $document, $project, $executor); } /** * @param string $collection collectionID * @param array $queries * @param Database $database - * @param callable|null $callback + * @param ?callable $callback * @return void - * @throws Exception + * @throws DatabaseException */ - protected function deleteByGroup(string $collection, array $queries, Database $database, callable $callback = null): void - { - $count = 0; - $chunk = 0; - $limit = 50; - $sum = $limit; + protected function deleteByGroup( + string $collection, + array $queries, + Database $database, + ?callable $callback = null + ): void { + $start = \microtime(true); - $executionStart = \microtime(true); + /** + * deleteDocuments uses a cursor, we need to add a unique order by field or use default + */ - while ($sum === $limit) { - $chunk++; + try { + $documents = $database->deleteDocuments($collection, $queries); + } catch (Throwable $th) { + $tenant = $database->getSharedTables() ? 'Tenant:'.$database->getTenant() : ''; + Console::error("Failed to delete documents for collection:{$database->getNamespace()}_{$collection} {$tenant} :{$th->getMessage()}"); + return; + } - try { - $results = $database->find($collection, [Query::limit($limit), ...$queries]); - } catch (DatabaseException $e) { - Console::error('Failed to find documents for collection ' . $collection . ': ' . $e->getMessage()); - return; - } - - $sum = count($results); - - Console::info('Deleting chunk #' . $chunk . '. Found ' . $sum . ' documents'); - - foreach ($results as $document) { - $this->deleteById($document, $database, $callback); - $count++; + if (\is_callable($callback)) { + foreach ($documents as $document) { + $callback($document); } } - $executionEnd = \microtime(true); + $end = \microtime(true); + $count = \count($documents); - Console::info("Deleted {$count} document by group in " . ($executionEnd - $executionStart) . " seconds"); + Console::info("Deleted {$count} documents by group in " . ($end - $start) . " seconds"); } /** @@ -997,25 +1237,23 @@ class Deletes extends Action protected function listByGroup(string $collection, array $queries, Database $database, callable $callback = null): void { $count = 0; - $chunk = 0; - $limit = 50; - $results = []; + $limit = 1000; $sum = $limit; $cursor = null; - $executionStart = \microtime(true); + $start = \microtime(true); while ($sum === $limit) { - $chunk++; - $mergedQueries = \array_merge([Query::limit($limit)], $queries); - if ($cursor instanceof Document) { - $mergedQueries[] = Query::cursorAfter($cursor); + $queries = \array_merge([Query::limit($limit)], $queries); + + if ($cursor !== null) { + $queries[] = Query::cursorAfter($cursor); } - $results = $database->find($collection, $mergedQueries); + $results = $database->find($collection, $queries); - $sum = count($results); + $sum = \count($results); if ($sum > 0) { $cursor = $results[$sum - 1]; @@ -1030,35 +1268,24 @@ class Deletes extends Action } } - $executionEnd = \microtime(true); + $end = \microtime(true); - Console::info("Listed {$count} document by group in " . ($executionEnd - $executionStart) . " seconds"); + Console::info("Listed {$count} documents by group in " . ($end - $start) . " seconds"); } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Document $document rule document * @return void */ - private function deleteRule(Database $dbForConsole, Document $document): void + private function deleteRule(Database $dbForPlatform, Document $document, CertificatesAdapter $certificates): void { - $domain = $document->getAttribute('domain'); - $directory = APP_STORAGE_CERTIFICATES . '/' . $domain; - $checkTraversal = realpath($directory) === $directory; - - if ($checkTraversal && is_dir($directory)) { - // Delete files, so Traefik is aware of change - array_map('unlink', glob($directory . '/*.*')); - rmdir($directory); - Console::info("Deleted certificate files for {$domain}"); - } else { - Console::info("No certificate files found for {$domain}"); - } + $certificates->deleteCertificate($domain); // Delete certificate document, so Appwrite is aware of change if (isset($document['certificateId'])) { - $dbForConsole->deleteDocument('certificates', $document['certificateId']); + $dbForPlatform->deleteDocument('certificates', $document['certificateId']); } } @@ -1079,21 +1306,21 @@ class Deletes extends Action } /** - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param callable $getProjectDB * @param Document $document * @param Document $project * @return void * @throws Exception */ - private function deleteInstallation(Database $dbForConsole, callable $getProjectDB, Document $document, Document $project): void + private function deleteInstallation(Database $dbForPlatform, callable $getProjectDB, Document $document, Document $project): void { $dbForProject = $getProjectDB($project); $this->listByGroup('functions', [ Query::equal('installationInternalId', [$document->getInternalId()]) - ], $dbForProject, function ($function) use ($dbForProject, $dbForConsole) { - $dbForConsole->deleteDocument('repositories', $function->getAttribute('repositoryId')); + ], $dbForProject, function ($function) use ($dbForProject, $dbForPlatform) { + $dbForPlatform->deleteDocument('repositories', $function->getAttribute('repositoryId')); $function = $function ->setAttribute('installationId', '') @@ -1112,13 +1339,12 @@ class Deletes extends Action * @param callable $getProjectDB * @param ?Document $function * @param Document $project + * @param Executor $executor * @return void * @throws Exception */ - private function deleteRuntimes(callable $getProjectDB, ?Document $function, Document $project): void + private function deleteRuntimes(callable $getProjectDB, ?Document $function, Document $project, Executor $executor): void { - $executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST')); - $deleteByFunction = function (Document $function) use ($getProjectDB, $project, $executor) { $this->listByGroup( 'deployments', diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 72a3334f2f..c8c68a58ba 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -5,8 +5,9 @@ namespace Appwrite\Platform\Workers; use Ahc\Jwt\JWT; use Appwrite\Event\Event; use Appwrite\Event\Func; -use Appwrite\Event\Usage; -use Appwrite\Messaging\Adapter\Realtime; +use Appwrite\Event\Realtime; +use Appwrite\Event\StatsUsage; +use Appwrite\Event\Webhook; use Appwrite\Utopia\Response\Model\Execution; use Exception; use Executor\Executor; @@ -44,16 +45,30 @@ class Functions extends Action ->inject('project') ->inject('message') ->inject('dbForProject') + ->inject('queueForWebhooks') ->inject('queueForFunctions') + ->inject('queueForRealtime') ->inject('queueForEvents') - ->inject('queueForUsage') + ->inject('queueForStatsUsage') ->inject('log') + ->inject('executor') ->inject('isResourceBlocked') - ->callback(fn (Document $project, Message $message, Database $dbForProject, Func $queueForFunctions, Event $queueForEvents, Usage $queueForUsage, Log $log, callable $isResourceBlocked) => $this->action($project, $message, $dbForProject, $queueForFunctions, $queueForEvents, $queueForUsage, $log, $isResourceBlocked)); + ->callback([$this, 'action']); } - public function action(Document $project, Message $message, Database $dbForProject, Func $queueForFunctions, Event $queueForEvents, Usage $queueForUsage, Log $log, callable $isResourceBlocked): void - { + public function action( + Document $project, + Message $message, + Database $dbForProject, + Webhook $queueForWebhooks, + Func $queueForFunctions, + Realtime $queueForRealtime, + Event $queueForEvents, + StatsUsage $queueForStatsUsage, + Log $log, + Executor $executor, + callable $isResourceBlocked + ): void { $payload = $message->getPayload() ?? []; if (empty($payload)) { @@ -136,11 +151,14 @@ class Functions extends Action $this->execute( log: $log, dbForProject: $dbForProject, + queueForWebhooks: $queueForWebhooks, queueForFunctions: $queueForFunctions, - queueForUsage: $queueForUsage, + queueForRealtime: $queueForRealtime, + queueForStatsUsage: $queueForStatsUsage, queueForEvents: $queueForEvents, project: $project, function: $function, + executor: $executor, trigger: 'event', path: '/', method: 'POST', @@ -176,11 +194,14 @@ class Functions extends Action $this->execute( log: $log, dbForProject: $dbForProject, + queueForWebhooks: $queueForWebhooks, queueForFunctions: $queueForFunctions, - queueForUsage: $queueForUsage, + queueForRealtime: $queueForRealtime, + queueForStatsUsage: $queueForStatsUsage, queueForEvents: $queueForEvents, project: $project, function: $function, + executor: $executor, trigger: 'http', path: $path, method: $method, @@ -198,11 +219,14 @@ class Functions extends Action $this->execute( log: $log, dbForProject: $dbForProject, + queueForWebhooks: $queueForWebhooks, queueForFunctions: $queueForFunctions, - queueForUsage: $queueForUsage, + queueForRealtime: $queueForRealtime, + queueForStatsUsage: $queueForStatsUsage, queueForEvents: $queueForEvents, project: $project, function: $function, + executor: $executor, trigger: 'schedule', path: $path, method: $method, @@ -256,8 +280,9 @@ class Functions extends Action $execution = new Document([ '$id' => $executionId, '$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))], - 'functionInternalId' => $function->getInternalId(), - 'functionId' => $function->getId(), + 'resourceInternalId' => $function->getInternalId(), + 'resourceId' => $function->getId(), + 'resourceType' => 'functions', 'deploymentInternalId' => '', 'deploymentId' => '', 'trigger' => $trigger, @@ -270,7 +295,6 @@ class Functions extends Action 'errors' => $message, 'logs' => '', 'duration' => 0.0, - 'search' => implode(' ', [$function->getId(), $executionId]), ]); $execution = $dbForProject->createDocument('executions', $execution); @@ -284,10 +308,12 @@ class Functions extends Action * @param Log $log * @param Database $dbForProject * @param Func $queueForFunctions - * @param Usage $queueForUsage + * @param Realtime $queueForRealtime + * @param StatsUsage $queueForStatsUsage * @param Event $queueForEvents * @param Document $project * @param Document $function + * @param Executor $executor * @param string $trigger * @param string $path * @param string $method @@ -307,11 +333,14 @@ class Functions extends Action private function execute( Log $log, Database $dbForProject, + Webhook $queueForWebhooks, Func $queueForFunctions, - Usage $queueForUsage, + Realtime $queueForRealtime, + StatsUsage $queueForStatsUsage, Event $queueForEvents, Document $project, Document $function, + Executor $executor, string $trigger, string $path, string $method, @@ -325,8 +354,8 @@ class Functions extends Action ): void { $user ??= new Document(); $functionId = $function->getId(); - $deploymentId = $function->getAttribute('deployment', ''); - $spec = Config::getParam('runtime-specifications')[$function->getAttribute('specification', APP_FUNCTION_SPECIFICATION_DEFAULT)]; + $deploymentId = $function->getAttribute('deploymentId', ''); + $spec = Config::getParam('specifications')[$function->getAttribute('specification', APP_COMPUTE_SPECIFICATION_DEFAULT)]; $log->addTag('deploymentId', $deploymentId); @@ -345,19 +374,7 @@ class Functions extends Action return; } - $buildId = $deployment->getAttribute('buildId', ''); - - $log->addTag('buildId', $buildId); - - /** Check if build has exists */ - $build = $dbForProject->getDocument('builds', $buildId); - if ($build->isEmpty()) { - $errorMessage = 'The execution could not be completed because a corresponding deployment was not found. A function deployment needs to be created before it can be executed. Please create a deployment for your function and try again.'; - $this->fail($errorMessage, $dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); - return; - } - - if ($build->getAttribute('status') !== 'ready') { + if ($deployment->getAttribute('status') !== 'ready') { $errorMessage = 'The execution could not be completed because the build is not ready. Please wait for the build to complete and try again.'; $this->fail($errorMessage, $dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); return; @@ -403,8 +420,9 @@ class Functions extends Action $execution = new Document([ '$id' => $executionId, '$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))], - 'functionInternalId' => $function->getInternalId(), - 'functionId' => $function->getId(), + 'resourceInternalId' => $function->getInternalId(), + 'resourceId' => $function->getId(), + 'resourceType' => 'functions', 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentId' => $deployment->getId(), 'trigger' => $trigger, @@ -417,7 +435,6 @@ class Functions extends Action 'errors' => '', 'logs' => '', 'duration' => 0.0, - 'search' => implode(' ', [$functionId, $executionId]), ]); $execution = $dbForProject->createDocument('executions', $execution); @@ -479,8 +496,8 @@ class Functions extends Action 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', - 'APPWRITE_FUNCTION_CPUS' => ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT), - 'APPWRITE_FUNCTION_MEMORY' => ($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT), + 'APPWRITE_FUNCTION_CPUS' => ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT), + 'APPWRITE_FUNCTION_MEMORY' => ($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT), 'APPWRITE_VERSION' => APP_VERSION_STABLE, 'APPWRITE_REGION' => $project->getAttribute('region'), 'APPWRITE_DEPLOYMENT_TYPE' => $deployment->getAttribute('type', ''), @@ -502,7 +519,6 @@ class Functions extends Action try { $version = $function->getAttribute('version', 'v2'); $command = $runtime['startCommand']; - $executor = new Executor(System::getEnv('_APP_EXECUTOR_HOST')); $command = $version === 'v2' ? '' : 'cp /tmp/code.tar.gz /mnt/code/code.tar.gz && nohup helpers/start.sh "' . $command . '"'; $executionResponse = $executor->createExecution( projectId: $project->getId(), @@ -511,15 +527,15 @@ class Functions extends Action variables: $vars, timeout: $function->getAttribute('timeout', 0), image: $runtime['image'], - source: $build->getAttribute('path', ''), + source: $deployment->getAttribute('buildPath', ''), entrypoint: $deployment->getAttribute('entrypoint', ''), version: $version, path: $path, method: $method, headers: $headers, runtimeEntrypoint: $command, - cpus: $spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT, - memory: $spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT, + cpus: $spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT, + memory: $spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT, logging: $function->getAttribute('logging', true), ); @@ -552,32 +568,38 @@ class Functions extends Action $errorCode = $th->getCode(); } finally { /** Trigger usage queue */ - $queueForUsage + $queueForStatsUsage ->setProject($project) ->addMetric(METRIC_EXECUTIONS, 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_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(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(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(['{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(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))) ->trigger() ; } - $execution = $dbForProject->updateDocument('executions', $executionId, $execution); - /** Trigger Webhook */ $executionModel = new Execution(); + $realtimeExecution = $executionModel->filter(new Document($execution->getArrayCopy())); + $realtimeExecution = $realtimeExecution->getArrayCopy(\array_keys($executionModel->getRules())); + $queueForEvents - ->setQueue(Event::WEBHOOK_QUEUE_NAME) - ->setClass(Event::WEBHOOK_CLASS_NAME) ->setProject($project) ->setUser($user) ->setEvent('functions.[functionId].executions.[executionId].update') ->setParam('functionId', $function->getId()) ->setParam('executionId', $execution->getId()) - ->setPayload($execution->getArrayCopy(array_keys($executionModel->getRules()))) + ->setPayload($realtimeExecution); + + /** Trigger Webhook */ + $queueForWebhooks + ->from($queueForEvents) ->trigger(); /** Trigger Functions */ @@ -585,31 +607,11 @@ class Functions extends Action ->from($queueForEvents) ->trigger(); - /** Trigger realtime event */ - $allEvents = Event::generateEvents('functions.[functionId].executions.[executionId].update', [ - 'functionId' => $function->getId(), - 'executionId' => $execution->getId() - ]); - $target = Realtime::fromPayload( - // Pass first, most verbose event pattern - event: $allEvents[0], - payload: $execution, - project: $project - ); - Realtime::send( - projectId: 'console', - payload: $execution->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'] - ); - Realtime::send( - projectId: $project->getId(), - payload: $execution->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'] - ); + /** Trigger Realtime Events */ + $queueForRealtime + ->setSubscribers(['console', $project->getId()]) + ->from($queueForEvents) + ->trigger(); if (!empty($error)) { throw new Exception($error, $errorCode); diff --git a/src/Appwrite/Platform/Workers/Mails.php b/src/Appwrite/Platform/Workers/Mails.php index e48f96ea90..3a15182e51 100644 --- a/src/Appwrite/Platform/Workers/Mails.php +++ b/src/Appwrite/Platform/Workers/Mails.php @@ -29,7 +29,7 @@ class Mails extends Action ->inject('message') ->inject('register') ->inject('log') - ->callback(fn (Message $message, Registry $register, Log $log) => $this->action($message, $register, $log)); + ->callback([$this, 'action']); } /** diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 58f6265ff4..6f94764bbf 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -2,7 +2,7 @@ namespace Appwrite\Platform\Workers; -use Appwrite\Event\Usage; +use Appwrite\Event\StatsUsage; use Appwrite\Messaging\Status as MessageStatus; use Swoole\Runtime; use Utopia\CLI\Console; @@ -22,6 +22,8 @@ use Utopia\Messaging\Adapter\Push\APNS; use Utopia\Messaging\Adapter\Push as PushAdapter; use Utopia\Messaging\Adapter\Push\FCM; use Utopia\Messaging\Adapter\SMS as SMSAdapter; +use Utopia\Messaging\Adapter\SMS\Fast2SMS; +use Utopia\Messaging\Adapter\SMS\GEOSMS; use Utopia\Messaging\Adapter\SMS\Mock; use Utopia\Messaging\Adapter\SMS\Msg91; use Utopia\Messaging\Adapter\SMS\Telesign; @@ -32,6 +34,7 @@ use Utopia\Messaging\Messages\Email; use Utopia\Messaging\Messages\Email\Attachment; use Utopia\Messaging\Messages\Push; use Utopia\Messaging\Messages\SMS; +use Utopia\Messaging\Priority; use Utopia\Platform\Action; use Utopia\Queue\Message; use Utopia\Storage\Device; @@ -45,6 +48,8 @@ class Messaging extends Action { private ?Local $localDevice = null; + private ?SMSAdapter $adapter = null; + public static function getName(): string { return 'messaging'; @@ -55,31 +60,37 @@ class Messaging extends Action */ public function __construct() { + + $this->adapter = $this->createInternalSMSAdapter(); + $this ->desc('Messaging worker') ->inject('message') + ->inject('project') ->inject('log') ->inject('dbForProject') ->inject('deviceForFiles') - ->inject('queueForUsage') - ->callback(fn (Message $message, Log $log, Database $dbForProject, Device $deviceForFiles, Usage $queueForUsage) => $this->action($message, $log, $dbForProject, $deviceForFiles, $queueForUsage)); + ->inject('queueForStatsUsage') + ->callback([$this, 'action']); } /** * @param Message $message + * @param Document $project * @param Log $log * @param Database $dbForProject * @param Device $deviceForFiles - * @param Usage $queueForUsage + * @param StatsUsage $queueForStatsUsage * @return void * @throws \Exception */ public function action( Message $message, + Document $project, Log $log, Database $dbForProject, Device $deviceForFiles, - Usage $queueForUsage + StatsUsage $queueForStatsUsage ): void { Runtime::setHookFlags(SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_TCP); $payload = $message->getPayload() ?? []; @@ -89,19 +100,18 @@ class Messaging extends Action } $type = $payload['type'] ?? ''; - $project = new Document($payload['project'] ?? []); switch ($type) { case MESSAGE_SEND_TYPE_INTERNAL: $message = new Document($payload['message'] ?? []); $recipients = $payload['recipients'] ?? []; - $this->sendInternalSMSMessage($message, $project, $recipients, $queueForUsage, $log); + $this->sendInternalSMSMessage($message, $project, $recipients, $log); break; case MESSAGE_SEND_TYPE_EXTERNAL: $message = $dbForProject->getDocument('messages', $payload['messageId']); - $this->sendExternalMessage($dbForProject, $message, $deviceForFiles, $project, $queueForUsage); + $this->sendExternalMessage($dbForProject, $message, $deviceForFiles, $project, $queueForStatsUsage); break; default: throw new \Exception('Unknown message type: ' . $type); @@ -113,7 +123,7 @@ class Messaging extends Action Document $message, Device $deviceForFiles, Document $project, - Usage $queueForUsage + StatsUsage $queueForStatsUsage ): void { $topicIds = $message->getAttribute('topics', []); $targetIds = $message->getAttribute('targets', []); @@ -219,8 +229,8 @@ class Messaging extends Action /** * @var array<array> $results */ - $results = batch(\array_map(function ($providerId) use ($identifiers, &$providers, $default, $message, $dbForProject, $deviceForFiles, $project, $queueForUsage) { - return function () use ($providerId, $identifiers, &$providers, $default, $message, $dbForProject, $deviceForFiles, $project, $queueForUsage) { + $results = batch(\array_map(function ($providerId) use ($identifiers, &$providers, $default, $message, $dbForProject, $deviceForFiles, $project, $queueForStatsUsage) { + return function () use ($providerId, $identifiers, &$providers, $default, $message, $dbForProject, $deviceForFiles, $project, $queueForStatsUsage) { if (\array_key_exists($providerId, $providers)) { $provider = $providers[$providerId]; } else { @@ -247,8 +257,8 @@ class Messaging extends Action $adapter->getMaxMessagesPerRequest() ); - return batch(\array_map(function ($batch) use ($message, $provider, $adapter, $dbForProject, $deviceForFiles, $project, $queueForUsage) { - return function () use ($batch, $message, $provider, $adapter, $dbForProject, $deviceForFiles, $project, $queueForUsage) { + return batch(\array_map(function ($batch) use ($message, $provider, $adapter, $dbForProject, $deviceForFiles, $project, $queueForStatsUsage) { + return function () use ($batch, $message, $provider, $adapter, $dbForProject, $deviceForFiles, $project, $queueForStatsUsage) { $deliveredTotal = 0; $deliveryErrors = []; $messageData = clone $message; @@ -275,7 +285,7 @@ class Messaging extends Action Query::equal('identifier', [$result['recipient']]) ]); - if ($target instanceof Document && !$target->isEmpty()) { + if (!$target->isEmpty()) { $dbForProject->updateDocument( 'targets', $target->getId(), @@ -287,8 +297,8 @@ class Messaging extends Action } catch (\Throwable $e) { $deliveryErrors[] = 'Failed sending to targets with error: ' . $e->getMessage(); } finally { - $errorTotal = count($deliveryErrors); - $queueForUsage + $errorTotal = \count($deliveryErrors); + $queueForStatsUsage ->setProject($project) ->addMetric(METRIC_MESSAGES, ($deliveredTotal + $errorTotal)) ->addMetric(METRIC_MESSAGES_SENT, $deliveredTotal) @@ -333,7 +343,6 @@ class Messaging extends Action $message->setAttribute('status', MessageStatus::SENT); } - $message->removeAttribute('to'); foreach ($providers as $provider) { @@ -377,112 +386,40 @@ class Messaging extends Action } } - private function sendInternalSMSMessage(Document $message, Document $project, array $recipients, Usage $queueForUsage, Log $log): void + private function sendInternalSMSMessage(Document $message, Document $project, array $recipients, Log $log): void { - if (empty(System::getEnv('_APP_SMS_PROVIDER')) || empty(System::getEnv('_APP_SMS_FROM'))) { - throw new \Exception('Skipped SMS processing. Missing "_APP_SMS_PROVIDER" or "_APP_SMS_FROM" environment variables.'); + if ($this->adapter === null) { + Console::warning('Skipped SMS processing. SMS adapter is not set.'); + return; } if ($project->isEmpty()) { throw new \Exception('Project not set in payload'); } - Console::log('Project: ' . $project->getId()); - + Console::log('Processing project: ' . $project->getId()); $denyList = System::getEnv('_APP_SMS_PROJECTS_DENY_LIST', ''); $denyList = explode(',', $denyList); - if (\in_array($project->getId(), $denyList)) { Console::error('Project is in the deny list. Skipping...'); return; } - $smsDSN = new DSN(System::getEnv('_APP_SMS_PROVIDER')); - $host = $smsDSN->getHost(); - $password = $smsDSN->getPassword(); - $user = $smsDSN->getUser(); - - $log->addTag('type', $host); - - $from = System::getEnv('_APP_SMS_FROM'); - - $provider = new Document([ - '$id' => ID::unique(), - 'provider' => $host, - 'type' => MESSAGE_TYPE_SMS, - 'name' => 'Internal SMS', - 'enabled' => true, - 'credentials' => match ($host) { - 'twilio' => [ - 'accountSid' => $user, - 'authToken' => $password, - // Twilio Messaging Service SIDs always start with MG - // https://www.twilio.com/docs/messaging/services - 'messagingServiceSid' => \str_starts_with($from, 'MG') ? $from : null - ], - 'textmagic' => [ - 'username' => $user, - 'apiKey' => $password - ], - 'telesign' => [ - 'customerId' => $user, - 'apiKey' => $password - ], - 'msg91' => [ - 'senderId' => $user, - 'authKey' => $password, - 'templateId' => $smsDSN->getParam('templateId', $from), - ], - 'vonage' => [ - 'apiKey' => $user, - 'apiSecret' => $password - ], - default => null - }, - 'options' => match ($host) { - 'twilio' => [ - 'from' => \str_starts_with($from, 'MG') ? null : $from - ], - default => [ - 'from' => $from - ] - } - ]); - - $adapter = $this->getSmsAdapter($provider); - - $batches = \array_chunk( + $from = System::getEnv('_APP_SMS_FROM', ''); + $sms = new SMS( $recipients, - $adapter->getMaxMessagesPerRequest() + $message->getAttribute('data')['content'], + $from ); - batch(\array_map(function ($batch) use ($message, $provider, $adapter, $project, $queueForUsage) { - return function () use ($batch, $message, $provider, $adapter, $project, $queueForUsage) { - $message->setAttribute('to', $batch); - - $data = $this->buildSmsMessage($message, $provider); - - try { - $adapter->send($data); - - $countryCode = $adapter->getCountryCode($message['to'][0] ?? ''); - if (!empty($countryCode)) { - $queueForUsage - ->addMetric(str_replace('{countryCode}', $countryCode, METRIC_AUTH_METHOD_PHONE_COUNTRY_CODE), 1); - } - $queueForUsage - ->addMetric(METRIC_AUTH_METHOD_PHONE, 1) - ->setProject($project) - ->trigger(); - } catch (\Throwable $th) { - throw new \Exception('Failed sending to targets with error: ' . $th->getMessage()); - } - }; - }, $batches)); + try { + $result = $this->adapter->send($sms); + } catch (\Throwable $th) { + throw new \Exception('Failed sending to targets with error: ' . $th->getMessage()); + } } - private function getSmsAdapter(Document $provider): ?SMSAdapter { $credentials = $provider->getAttribute('credentials'); @@ -512,6 +449,12 @@ class Messaging extends Action $credentials['apiKey'] ?? '', $credentials['apiSecret'] ?? '' ), + 'fast2sms' => new Fast2SMS( + $credentials['apiKey'] ?? '', + $credentials['senderId'] ?? '', + $credentials['messageId'] ?? '', + $credentials['useDLT'] ?? true + ), default => null }; } @@ -676,8 +619,8 @@ class Messaging extends Action private function buildPushMessage(Document $message): Push { $to = $message['to']; - $title = $message['data']['title']; - $body = $message['data']['body']; + $title = $message['data']['title'] ?? null; + $body = $message['data']['body'] ?? null; $data = $message['data']['data'] ?? null; $action = $message['data']['action'] ?? null; $image = $message['data']['image']['url'] ?? null; @@ -686,6 +629,21 @@ class Messaging extends Action $color = $message['data']['color'] ?? null; $tag = $message['data']['tag'] ?? null; $badge = $message['data']['badge'] ?? null; + $contentAvailable = $message['data']['contentAvailable'] ?? null; + $critical = $message['data']['critical'] ?? null; + $priority = $message['data']['priority'] ?? null; + + if ($title === '') { + $title = null; + } + if ($body === '') { + $body = null; + } + if ($priority !== null) { + $priority = $priority === 'high' + ? Priority::HIGH + : Priority::NORMAL; + } return new Push( $to, @@ -698,7 +656,10 @@ class Messaging extends Action $icon, $color, $tag, - $badge + $badge, + $contentAvailable, + $critical, + $priority ); } @@ -710,4 +671,127 @@ class Messaging extends Action return $this->localDevice; } + + private function createInternalSMSAdapter(): ?SMSAdapter + { + if (empty(System::getEnv('_APP_SMS_PROVIDER')) || empty(System::getEnv('_APP_SMS_FROM'))) { + Console::warning('Skipped SMS processing. Missing "_APP_SMS_PROVIDER" or "_APP_SMS_FROM" environment variables.'); + return null; + } + + $providers = System::getEnv('_APP_SMS_PROVIDER', ''); + + $dsns = []; + if (!empty($providers)) { + $providers = explode(',', $providers); + foreach ($providers as $provider) { + $dsns[] = new DSN($provider); + } + } + + if (count($dsns) === 1) { + $provider = $this->createProviderFromDSN($dsns[0]); + $adapter = $this->getSmsAdapter($provider); + return $adapter; + } + + $defaultDSN = null; + $localDSNs = []; + + /** @var DSN $dsn */ + foreach ($dsns as $dsn) { + if ($dsn->getParam('local', '') === 'default') { + $defaultDSN = $dsn; + } else { + $localDSNs[] = $dsn; + } + } + + if ($defaultDSN === null) { + throw new \Exception('No default SMS provider found'); + } + + $defaultProvider = $this->createProviderFromDSN($defaultDSN); + $adapter = $this->getSmsAdapter($defaultProvider); + $geosms = new GEOSMS($adapter); + + /** @var DSN $localDSN */ + foreach ($localDSNs as $localDSN) { + try { + $provider = $this->createProviderFromDSN($localDSN); + $adapter = $this->getSmsAdapter($provider); + } catch (\Exception) { + Console::warning('Unable to create adapter: ' . $localDSN->getHost()); + continue; + } + + $callingCode = $localDSN->getParam('local', ''); + if (empty($callingCode)) { + Console::warning('Unable to register adapter: ' . $localDSN->getHost() . '. Missing `local` parameter.'); + continue; + } + + $geosms->setLocal($callingCode, $adapter); + } + return $geosms; + } + + private function createProviderFromDSN(DSN $dsn): Document + { + $host = $dsn->getHost(); + $password = $dsn->getPassword(); + $user = $dsn->getUser(); + $from = System::getEnv('_APP_SMS_FROM'); + + $provider = new Document([ + '$id' => ID::unique(), + 'provider' => $host, + 'type' => MESSAGE_TYPE_SMS, + 'name' => 'Internal SMS', + 'enabled' => true, + 'credentials' => match ($host) { + 'twilio' => [ + 'accountSid' => $user, + 'authToken' => $password, + // Twilio Messaging Service SIDs always start with MG + // https://www.twilio.com/docs/messaging/services + 'messagingServiceSid' => \str_starts_with($from, 'MG') ? $from : null + ], + 'textmagic' => [ + 'username' => $user, + 'apiKey' => $password + ], + 'telesign' => [ + 'customerId' => $user, + 'apiKey' => $password + ], + 'msg91' => [ + 'senderId' => $user, + 'authKey' => $password, + 'templateId' => $dsn->getParam('templateId', $from), + ], + 'vonage' => [ + 'apiKey' => $user, + 'apiSecret' => $password + ], + 'fast2sms' => [ + 'senderId' => $user, + 'apiKey' => $password, + 'messageId' => $dsn->getParam('messageId'), + 'useDLT' => $dsn->getParam('useDLT'), + ], + default => null + }, + 'options' => match ($host) { + 'twilio' => [ + 'from' => \str_starts_with($from, 'MG') ? null : $from + ], + default => [ + 'from' => $from + ] + } + ]); + + return $provider; + } } diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 4b1926ed26..b009da0718 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -2,10 +2,8 @@ namespace Appwrite\Platform\Workers; -use Appwrite\Event\Event; -use Appwrite\Messaging\Adapter\Realtime; -use Appwrite\Permission; -use Appwrite\Role; +use Ahc\Jwt\JWT; +use Appwrite\Event\Realtime; use Exception; use Utopia\CLI\Console; use Utopia\Config\Config; @@ -15,28 +13,36 @@ use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Restricted; use Utopia\Database\Exception\Structure; -use Utopia\Database\Helpers\ID; -use Utopia\Logger\Log; use Utopia\Migration\Destination; use Utopia\Migration\Destinations\Appwrite as DestinationAppwrite; use Utopia\Migration\Exception as MigrationException; use Utopia\Migration\Source; use Utopia\Migration\Sources\Appwrite as SourceAppwrite; +use Utopia\Migration\Sources\CSV; use Utopia\Migration\Sources\Firebase; use Utopia\Migration\Sources\NHost; use Utopia\Migration\Sources\Supabase; use Utopia\Migration\Transfer; use Utopia\Platform\Action; use Utopia\Queue\Message; +use Utopia\Storage\Device; +use Utopia\System\System; class Migrations extends Action { protected Database $dbForProject; - protected Database $dbForConsole; + protected Database $dbForPlatform; + + protected Device $deviceForImports; protected Document $project; + /** + * @var callable + */ + protected $logError; + public static function getName(): string { return 'migrations'; @@ -50,25 +56,28 @@ class Migrations extends Action $this ->desc('Migrations worker') ->inject('message') + ->inject('project') ->inject('dbForProject') - ->inject('dbForConsole') - ->inject('log') - ->callback(fn (Message $message, Database $dbForProject, Database $dbForConsole, Log $log) => $this->action($message, $dbForProject, $dbForConsole, $log)); + ->inject('dbForPlatform') + ->inject('logError') + ->inject('queueForRealtime') + ->inject('deviceForImports') + ->callback([$this, 'action']); } /** * @throws Exception */ - public function action(Message $message, Database $dbForProject, Database $dbForConsole, Log $log): void + public function action(Message $message, Document $project, Database $dbForProject, Database $dbForPlatform, callable $logError, Realtime $queueForRealtime, Device $deviceForImports): void { $payload = $message->getPayload() ?? []; + $this->deviceForImports = $deviceForImports; if (empty($payload)) { throw new Exception('Missing payload'); } $events = $payload['events'] ?? []; - $project = new Document($payload['project'] ?? []); $migration = new Document($payload['migration'] ?? []); if ($project->getId() === 'console') { @@ -76,8 +85,9 @@ class Migrations extends Action } $this->dbForProject = $dbForProject; - $this->dbForConsole = $dbForConsole; + $this->dbForPlatform = $dbForPlatform; $this->project = $project; + $this->logError = $logError; /** * Handle Event execution. @@ -86,10 +96,7 @@ class Migrations extends Action return; } - $log->addTag('migrationId', $migration->getId()); - $log->addTag('projectId', $project->getId()); - - $this->processMigration($migration, $log); + $this->processMigration($migration, $queueForRealtime); } /** @@ -98,7 +105,9 @@ class Migrations extends Action protected function processSource(Document $migration): Source { $source = $migration->getAttribute('source'); + $resourceId = $migration->getAttribute('resourceId'); $credentials = $migration->getAttribute('credentials'); + $migrationOptions = $migration->getAttribute('options'); return match ($source) { Firebase::getName() => new Firebase( @@ -127,6 +136,12 @@ class Migrations extends Action $credentials['endpoint'] === 'http://localhost/v1' ? 'http://appwrite/v1' : $credentials['endpoint'], $credentials['apiKey'], ), + CSV::getName() => new CSV( + $resourceId, + $migrationOptions['path'], + $this->deviceForImports, + $this->dbForProject + ), default => throw new \Exception('Invalid source type'), }; } @@ -157,98 +172,54 @@ class Migrations extends Action * @throws \Utopia\Database\Exception * @throws Exception */ - protected function updateMigrationDocument(Document $migration, Document $project): Document + protected function updateMigrationDocument(Document $migration, Document $project, Realtime $queueForRealtime): Document { - /** Trigger Realtime */ - $allEvents = Event::generateEvents('migrations.[migrationId].update', [ - 'migrationId' => $migration->getId(), - ]); - - $target = Realtime::fromPayload( - event: $allEvents[0], - payload: $migration, - project: $project - ); - - Realtime::send( - projectId: 'console', - payload: $migration->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'], - ); - - Realtime::send( - projectId: $project->getId(), - payload: $migration->getArrayCopy(), - events: $allEvents, - channels: $target['channels'], - roles: $target['roles'], - ); + /** Trigger Realtime Events */ + $queueForRealtime + ->setProject($project) + ->setSubscribers(['console', $project->getId()]) + ->setEvent('migrations.[migrationId].update') + ->setParam('migrationId', $migration->getId()) + ->setPayload($migration->getArrayCopy()) + ->trigger(); return $this->dbForProject->updateDocument('migrations', $migration->getId(), $migration); } /** - * @throws \Utopia\Database\Exception - * @throws Authorization - * @throws Conflict - * @throws Restricted - * @throws Structure - */ - protected function removeAPIKey(Document $apiKey): void - { - $this->dbForConsole->deleteDocument('keys', $apiKey->getId()); - } - - /** - * @throws Authorization - * @throws Structure - * @throws \Utopia\Database\Exception * @throws Exception */ - protected function generateAPIKey(Document $project): Document + protected function generateAPIKey(Document $project): string { - $generatedSecret = bin2hex(\random_bytes(128)); + $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 86400, 0); - $key = new Document([ - '$id' => ID::unique(), - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], - 'projectInternalId' => $project->getInternalId(), + $apiKey = $jwt->encode([ 'projectId' => $project->getId(), - 'name' => 'Transfer API Key', + 'disabledMetrics' => [ + METRIC_DATABASES_OPERATIONS_READS, + METRIC_DATABASES_OPERATIONS_WRITES, + METRIC_NETWORK_REQUESTS, + METRIC_NETWORK_INBOUND, + METRIC_NETWORK_OUTBOUND, + ], 'scopes' => [ 'users.read', 'users.write', 'teams.read', 'teams.write', - 'databases.read', - 'databases.write', - 'collections.read', - 'collections.write', - 'documents.read', - 'documents.write', 'buckets.read', 'buckets.write', 'files.read', 'files.write', 'functions.read', 'functions.write', + 'databases.read', + 'collections.read', + 'documents.read', ], - 'expire' => null, - 'sdks' => [], - 'accessedAt' => null, - 'secret' => $generatedSecret, ]); - $this->dbForConsole->createDocument('keys', $key); - $this->dbForConsole->purgeCachedDocument('projects', $project->getId()); - - return $key; + return API_KEY_DYNAMIC . '_' . $apiKey; } /** @@ -259,10 +230,10 @@ class Migrations extends Action * @throws \Utopia\Database\Exception * @throws Exception */ - protected function processMigration(Document $migration, Log $log): void + protected function processMigration(Document $migration, Realtime $queueForRealtime): void { $project = $this->project; - $projectDocument = $this->dbForConsole->getDocument('projects', $project->getId()); + $projectDocument = $this->dbForPlatform->getDocument('projects', $project->getId()); $tempAPIKey = $this->generateAPIKey($projectDocument); $transfer = $source = $destination = null; @@ -276,19 +247,17 @@ class Migrations extends Action $credentials['projectId'] = $credentials['projectId'] ?? $projectDocument->getId(); $credentials['endpoint'] = $credentials['endpoint'] ?? 'http://appwrite/v1'; - $credentials['apiKey'] = $credentials['apiKey'] ?? $tempAPIKey['secret']; + $credentials['apiKey'] = $credentials['apiKey'] ?? $tempAPIKey; $migration->setAttribute('credentials', $credentials); } $migration->setAttribute('stage', 'processing'); $migration->setAttribute('status', 'processing'); - $this->updateMigrationDocument($migration, $projectDocument); - - $log->addTag('type', $migration->getAttribute('source')); + $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); $source = $this->processSource($migration); - $destination = $this->processDestination($migration, $tempAPIKey->getAttribute('secret')); + $destination = $this->processDestination($migration, $tempAPIKey); $source->report(); @@ -299,14 +268,14 @@ class Migrations extends Action /** Start Transfer */ $migration->setAttribute('stage', 'migrating'); - $this->updateMigrationDocument($migration, $projectDocument); + $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); $transfer->run( $migration->getAttribute('resources'), - function () use ($migration, $transfer, $projectDocument) { + function () use ($migration, $transfer, $projectDocument, $queueForRealtime) { $migration->setAttribute('resourceData', json_encode($transfer->getCache())); $migration->setAttribute('statusCounters', json_encode($transfer->getStatusCounters())); - $this->updateMigrationDocument($migration, $projectDocument); + $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); }, $migration->getAttribute('resourceId'), $migration->getAttribute('resourceType') @@ -324,7 +293,6 @@ class Migrations extends Action $errorMessages = []; foreach ($sourceErrors as $error) { - /** @var $sourceErrors $error */ $message = "Error occurred while fetching '{$error->getResourceName()}:{$error->getResourceId()}' from source with message: '{$error->getMessage()}'"; if ($error->getPrevious()) { $message .= " Message: ".$error->getPrevious()->getMessage() . " File: ".$error->getPrevious()->getFile() . " Line: ".$error->getPrevious()->getLine(); @@ -344,8 +312,7 @@ class Migrations extends Action } $migration->setAttribute('errors', $errorMessages); - $log->addExtra('migrationErrors', json_encode($errorMessages)); - $this->updateMigrationDocument($migration, $projectDocument); + $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); return; } @@ -359,7 +326,12 @@ class Migrations extends Action if (! $migration->isEmpty()) { $migration->setAttribute('status', 'failed'); $migration->setAttribute('stage', 'finished'); - $migration->setAttribute('errors', [$th->getMessage()]); + + call_user_func($this->logError, $th, 'appwrite-worker', 'appwrite-queue-'.self::getName(), [ + 'migrationId' => $migration->getId(), + 'source' => $migration->getAttribute('source') ?? '', + 'destination' => $migration->getAttribute('destination') ?? '', + ]); return; } @@ -379,27 +351,47 @@ class Migrations extends Action } $migration->setAttribute('errors', $errorMessages); - $log->addTag('migrationErrors', json_encode($errorMessages)); } } finally { - if (! $tempAPIKey->isEmpty()) { - $this->removeAPIKey($tempAPIKey); - } - - $this->updateMigrationDocument($migration, $projectDocument); + $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().')'); - $destination->error(); - $source->error(); + if ($destination) { + $destination->error(); - throw new Exception('Migration failed'); + foreach ($destination->getErrors() as $error) { + /** @var MigrationException $error */ + call_user_func($this->logError, $error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [ + 'migrationId' => $migration->getId(), + 'source' => $migration->getAttribute('source') ?? '', + 'destination' => $migration->getAttribute('destination') ?? '', + 'resourceName' => $error->getResourceName(), + 'resourceGroup' => $error->getResourceGroup() + ]); + } + } + + if ($source) { + $source->error(); + + foreach ($source->getErrors() as $error) { + /** @var MigrationException $error */ + call_user_func($this->logError, $error, 'appwrite-worker', 'appwrite-queue-' . self::getName(), [ + 'migrationId' => $migration->getId(), + 'source' => $migration->getAttribute('source') ?? '', + 'destination' => $migration->getAttribute('destination') ?? '', + 'resourceName' => $error->getResourceName(), + 'resourceGroup' => $error->getResourceGroup() + ]); + } + } } if ($migration->getAttribute('status', '') === 'completed') { - $destination->success(); - $source->success(); + $destination?->success(); + $source?->success(); } } } diff --git a/src/Appwrite/Platform/Workers/StatsResources.php b/src/Appwrite/Platform/Workers/StatsResources.php new file mode 100644 index 0000000000..8b7c6df1ca --- /dev/null +++ b/src/Appwrite/Platform/Workers/StatsResources.php @@ -0,0 +1,443 @@ +<?php + +namespace Appwrite\Platform\Workers; + +use Appwrite\Platform\Action; +use Exception; +use Throwable; +use Utopia\CLI\Console; +use Utopia\Database\Database; +use Utopia\Database\Document; +use Utopia\Database\Query; +use Utopia\Queue\Message; + +class StatsResources extends Action +{ + /** + * Date format for different periods + */ + protected array $periods = [ + '1h' => 'Y-m-d H:00', + '1d' => 'Y-m-d 00:00', + 'inf' => '0000-00-00 00:00' + ]; + + /** + * @var array $documents + * + * Array of documents to batch write + * + */ + protected array $documents = []; + + public static function getName(): string + { + return 'stats-resources'; + } + + + /** + * @throws Exception + */ + public function __construct() + { + $this + ->desc('Stats resources worker') + ->inject('message') + ->inject('project') + ->inject('getProjectDB') + ->inject('getLogsDB') + ->inject('dbForPlatform') + ->inject('logError') + ->callback([$this, 'action']); + } + + /** + * @param Message $message + * @param Document $project + * @param callable $getProjectDB + * @return void + * @throws \Utopia\Database\Exception + * @throws Exception + */ + public function action(Message $message, Document $project, callable $getProjectDB, callable $getLogsDB, Database $dbForPlatform, callable $logError): void + { + $this->logError = $logError; + + $payload = $message->getPayload() ?? []; + if (empty($payload)) { + throw new Exception('Missing payload'); + } + + if (empty($project->getAttribute('database'))) { + var_dump($payload); + return; + } + + // Reset documents for each job + $this->documents = []; + + $startTime = microtime(true); + $this->countForProject($dbForPlatform, $getLogsDB, $getProjectDB, $project); + $endTime = microtime(true); + $executionTime = $endTime - $startTime; + Console::info('Project: ' . $project->getId() . '(' . $project->getInternalId() . ') aggregated in ' . $executionTime .' seconds'); + } + + protected function countForProject(Database $dbForPlatform, callable $getLogsDB, callable $getProjectDB, Document $project): void + { + Console::info('Begining count for: ' . $project->getId()); + + $dbForLogs = null; + $dbForProject = null; + try { + /** @var \Utopia\Database\Database $dbForLogs */ + $dbForLogs = call_user_func($getLogsDB, $project); + /** @var \Utopia\Database\Database $dbForProject */ + $dbForProject = call_user_func($getProjectDB, $project); + } catch (Throwable $th) { + Console::error('Unable to get database'); + Console::error($th->getMessage()); + return; + } + + try { + + $region = $project->getAttribute('region'); + + $platforms = $dbForPlatform->count('platforms', [ + Query::equal('projectInternalId', [$project->getInternalId()]) + ]); + $webhooks = $dbForPlatform->count('webhooks', [ + Query::equal('projectInternalId', [$project->getInternalId()]) + ]); + $keys = $dbForPlatform->count('keys', [ + Query::equal('projectInternalId', [$project->getInternalId()]) + ]); + + $domains = $dbForPlatform->count('rules', [ + Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('owner', ['']), + ]); + + + $databases = $dbForProject->count('databases'); + $buckets = $dbForProject->count('buckets'); + $users = $dbForProject->count('users'); + + $last30Days = (new \DateTime())->sub(\DateInterval::createFromDateString('30 days'))->format('Y-m-d 00:00:00'); + $usersMAU = $dbForProject->count('users', [ + Query::greaterThanEqual('accessedAt', $last30Days) + ]); + $last24Hours = (new \DateTime())->sub(\DateInterval::createFromDateString('24 hours'))->format('Y-m-d h:m:00'); + $usersDAU = $dbForProject->count('users', [ + Query::greaterThanEqual('accessedAt', $last24Hours) + ]); + $last7Days = (new \DateTime())->sub(\DateInterval::createFromDateString('7 days'))->format('Y-m-d 00:00:00'); + $usersWAU = $dbForProject->count('users', [ + Query::greaterThanEqual('accessedAt', $last7Days) + ]); + $teams = $dbForProject->count('teams'); + $functions = $dbForProject->count('functions'); + + $messages = $dbForProject->count('messages'); + $providers = $dbForProject->count('providers'); + $topics = $dbForProject->count('topics'); + $targets = $dbForProject->count('targets'); + $emailTargets = $dbForProject->count('targets', [ + Query::equal('providerType', [MESSAGE_TYPE_EMAIL]) + ]); + $pushTargets = $dbForProject->count('targets', [ + Query::equal('providerType', [MESSAGE_TYPE_PUSH]) + ]); + $smsTargets = $dbForProject->count('targets', [ + Query::equal('providerType', [MESSAGE_TYPE_SMS]) + ]); + + $metrics = [ + METRIC_DATABASES => $databases, + METRIC_BUCKETS => $buckets, + METRIC_USERS => $users, + METRIC_FUNCTIONS => $functions, + METRIC_TEAMS => $teams, + METRIC_MESSAGES => $messages, + METRIC_MAU => $usersMAU, + METRIC_DAU => $usersDAU, + METRIC_WAU => $usersWAU, + METRIC_WEBHOOKS => $webhooks, + METRIC_PLATFORMS => $platforms, + METRIC_PROVIDERS => $providers, + METRIC_TOPICS => $topics, + METRIC_KEYS => $keys, + METRIC_DOMAINS => $domains, + METRIC_TARGETS => $targets, + str_replace('{providerType}', MESSAGE_TYPE_EMAIL, METRIC_PROVIDER_TYPE_TARGETS) => $emailTargets, + str_replace('{providerType}', MESSAGE_TYPE_PUSH, METRIC_PROVIDER_TYPE_TARGETS) => $pushTargets, + str_replace('{providerType}', MESSAGE_TYPE_SMS, METRIC_PROVIDER_TYPE_TARGETS) => $smsTargets, + ]; + + foreach ($metrics as $metric => $value) { + $this->createStatsDocuments($region, $metric, $value); + } + + try { + $this->countForBuckets($dbForProject, $dbForLogs, $region); + } catch (Throwable $th) { + call_user_func_array($this->logError, [$th, "StatsResources", "count_for_buckets_{$project->getId()}"]); + } + + try { + $this->countImageTransformations($dbForProject, $dbForLogs, $region); + } catch (Throwable $th) { + call_user_func_array($this->logError, [$th, "StatsResources", "count_for_buckets_{$project->getId()}"]); + } + + try { + $this->countForDatabase($dbForProject, $region); + } catch (Throwable $th) { + call_user_func_array($this->logError, [$th, "StatsResources", "count_for_database_{$project->getId()}"]); + } + + try { + $this->countForSitesAndFunctions($dbForProject, $region); + } catch (Throwable $th) { + call_user_func_array($this->logError, [$th, "StatsResources", "count_for_functions_{$project->getId()}"]); + } + + $this->writeDocuments($dbForLogs, $project); + } catch (Throwable $th) { + call_user_func_array($this->logError, [$th, "StatsResources", "count_for_project_{$project->getId()}"]); + } + + Console::info('End of count for: ' . $project->getId()); + } + + protected function countForBuckets(Database $dbForProject, Database $dbForLogs, string $region) + { + $totalFiles = 0; + $totalStorage = 0; + $this->foreachDocument($dbForProject, 'buckets', [], function ($bucket) use ($dbForProject, $dbForLogs, $region, &$totalFiles, &$totalStorage) { + $files = $dbForProject->count('bucket_' . $bucket->getInternalId()); + + $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), 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); + $this->createStatsDocuments($region, $metric, $storage); + + $totalStorage += $storage; + $totalFiles += $files; + }); + + $this->createStatsDocuments($region, METRIC_FILES, $totalFiles); + $this->createStatsDocuments($region, METRIC_FILES_STORAGE, $totalStorage); + } + + /** + * Need separate function to count per period data + */ + protected function countImageTransformations(Database $dbForProject, Database $dbForLogs, string $region) + { + $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(), [ + Query::greaterThanEqual('transformedAt', $last30Days), + ]); + $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED); + $this->createStatsDocuments($region, $metric, $imageTransformations); + $totalImageTransformations += $imageTransformations; + }); + + $this->createStatsDocuments($region, METRIC_FILES_IMAGES_TRANSFORMED, $totalImageTransformations); + } + + protected function countForDatabase(Database $dbForProject, string $region) + { + $totalCollections = 0; + $totalDocuments = 0; + + $totalDatabaseStorage = 0; + + $this->foreachDocument($dbForProject, 'databases', [], function ($database) use ($dbForProject, $region, &$totalCollections, &$totalDocuments, &$totalDatabaseStorage) { + $collections = $dbForProject->count('database_' . $database->getInternalId()); + + $metric = str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS); + $this->createStatsDocuments($region, $metric, $collections); + + [$documents, $storage] = $this->countForCollections($dbForProject, $database, $region); + + $totalDatabaseStorage += $storage; + $totalDocuments += $documents; + $totalCollections += $collections; + }); + + $this->createStatsDocuments($region, METRIC_COLLECTIONS, $totalCollections); + $this->createStatsDocuments($region, METRIC_DOCUMENTS, $totalDocuments); + $this->createStatsDocuments($region, METRIC_DATABASES_STORAGE, $totalDatabaseStorage); + } + protected function countForCollections(Database $dbForProject, Document $database, string $region): array + { + $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->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); + $this->createStatsDocuments($region, $metric, $collectionStorage); + $databaseStorage += $collectionStorage; + + }); + + $metric = str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_DOCUMENTS); + $this->createStatsDocuments($region, $metric, $databaseDocuments); + + $metric = str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_STORAGE); + $this->createStatsDocuments($region, $metric, $databaseStorage); + + return [$databaseDocuments, $databaseStorage]; + } + + protected function countForSitesAndFunctions(Database $dbForProject, string $region): void + { + $deploymentsStorage = $dbForProject->sum('deployments', 'sourceSize'); + $buildsStorage = $dbForProject->sum('deployments', 'buildSize'); + $this->createStatsDocuments($region, METRIC_DEPLOYMENTS_STORAGE, $deploymentsStorage); + $this->createStatsDocuments($region, METRIC_BUILDS_STORAGE, $buildsStorage); + + $deployments = $dbForProject->count('deployments'); + $this->createStatsDocuments($region, METRIC_DEPLOYMENTS, $deployments); + $this->createStatsDocuments($region, METRIC_BUILDS, $deployments); + + $this->countForFunctions($dbForProject, $region); + $this->countForSites($dbForProject, $region); + } + + protected function countForFunctions(Database $dbForProject, string $region) + { + + $deploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ + Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]) + ]); + $buildsStorage = $dbForProject->sum('deployments', 'buildSize', [ + Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]) + ]); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), $deploymentsStorage); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS_STORAGE), $buildsStorage); + + $deployments = $dbForProject->count('deployments', [ + Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]) + ]); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_DEPLOYMENTS), $deployments); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS), $deployments); + + $this->foreachDocument($dbForProject, 'functions', [], function (Document $function) use ($dbForProject, $region) { + $functionDeploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ + Query::equal('resourceInternalId', [$function->getInternalId()]), + 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); + + $functionDeployments = $dbForProject->count('deployments', [ + Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), + ]); + $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->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), $functionDeployments); + + $functionBuildsStorage = 0; + + $this->foreachDocument($dbForProject, 'deployments', [ + 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->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $functionBuildsStorage); + }); + } + + protected function countForSites(Database $dbForProject, string $region) + { + + $deploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ + Query::equal('resourceType', [RESOURCE_TYPE_SITES]) + ]); + $buildsStorage = $dbForProject->sum('deployments', 'buildSize', [ + Query::equal('resourceType', [RESOURCE_TYPE_SITES]) + ]); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), $deploymentsStorage); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS_STORAGE), $buildsStorage); + + $deployments = $dbForProject->count('deployments', [ + Query::equal('resourceType', [RESOURCE_TYPE_SITES]) + ]); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_DEPLOYMENTS), $deployments); + $this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS), $deployments); + + $this->foreachDocument($dbForProject, 'sites', [], function (Document $site) use ($dbForProject, $region) { + $siteDeploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ + Query::equal('resourceInternalId', [$site->getInternalId()]), + 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); + + $siteDeployments = $dbForProject->count('deployments', [ + Query::equal('resourceInternalId', [$site->getInternalId()]), + Query::equal('resourceType', [RESOURCE_TYPE_SITES]), + ]); + $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->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), $siteDeployments); + + $siteBuildsStorage = $dbForProject->sum('deployments', 'buildSize', [ + Query::equal('resourceInternalId', [$site->getInternalId()]), + 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); + }); + } + + protected function createStatsDocuments(string $region, string $metric, int $value) + { + foreach ($this->periods as $period => $format) { + $time = 'inf' === $period ? null : \date($format, \time()); + $id = \md5("{$time}_{$period}_{$metric}"); + + $this->documents[] = new Document([ + '$id' => $id, + 'metric' => $metric, + 'period' => $period, + 'region' => $region, + 'value' => $value, + 'time' => $time, + ]); + } + } + + protected function writeDocuments(Database $dbForLogs, Document $project): void + { + $dbForLogs->createOrUpdateDocuments( + 'stats', + $this->documents + ); + $this->documents = []; + Console::success('Stats written to logs db for project: ' . $project->getId() . '(' . $project->getInternalId() . ')'); + } +} diff --git a/src/Appwrite/Platform/Workers/Usage.php b/src/Appwrite/Platform/Workers/StatsUsage.php similarity index 70% rename from src/Appwrite/Platform/Workers/Usage.php rename to src/Appwrite/Platform/Workers/StatsUsage.php index 034e558d5d..b4f54db285 100644 --- a/src/Appwrite/Platform/Workers/Usage.php +++ b/src/Appwrite/Platform/Workers/StatsUsage.php @@ -2,7 +2,7 @@ namespace Appwrite\Platform\Workers; -use Appwrite\Event\UsageDump; +use Appwrite\Event\StatsUsageDump; use Exception; use Utopia\CLI\Console; use Utopia\Database\DateTime; @@ -11,19 +11,26 @@ use Utopia\Platform\Action; use Utopia\Queue\Message; use Utopia\System\System; -class Usage extends Action +class StatsUsage extends Action { private array $stats = []; private int $lastTriggeredTime = 0; private int $keys = 0; private const INFINITY_PERIOD = '_inf_'; - private const KEYS_THRESHOLD = 10000; + private const BATCH_SIZE_DEVELOPMENT = 1; + private const BATCH_SIZE_PRODUCTION = 10_000; public static function getName(): string { - return 'usage'; + return 'stats-usage'; } + private function getBatchSize(): int + { + return System::getEnv('_APP_ENV', 'development') === 'development' + ? self::BATCH_SIZE_DEVELOPMENT + : self::BATCH_SIZE_PRODUCTION; + } /** * @throws Exception */ @@ -31,13 +38,11 @@ class Usage extends Action { $this - ->desc('Usage worker') - ->inject('message') - ->inject('getProjectDB') - ->inject('queueForUsageDump') - ->callback(function (Message $message, callable $getProjectDB, UsageDump $queueForUsageDump) { - $this->action($message, $getProjectDB, $queueForUsageDump); - }); + ->desc('Stats usage worker') + ->inject('message') + ->inject('getProjectDB') + ->inject('queueForStatsUsageDump') + ->callback([$this, 'action']); $this->lastTriggeredTime = time(); } @@ -45,12 +50,12 @@ class Usage extends Action /** * @param Message $message * @param callable $getProjectDB - * @param UsageDump $queueForUsageDump + * @param StatsUsageDump $queueForStatsUsageDump * @return void * @throws \Utopia\Database\Exception * @throws Exception */ - public function action(Message $message, callable $getProjectDB, UsageDump $queueForUsageDump): void + public function action(Message $message, callable $getProjectDB, StatsUsageDump $queueForStatsUsageDump): void { $payload = $message->getPayload() ?? []; if (empty($payload)) { @@ -88,12 +93,12 @@ class Usage extends Action // If keys crossed threshold or X time passed since the last send and there are some keys in the array ($this->stats) if ( - $this->keys >= self::KEYS_THRESHOLD || + $this->keys >= $this->getBatchSize() || (time() - $this->lastTriggeredTime > $aggregationInterval && $this->keys > 0) ) { Console::warning('[' . DateTime::now() . '] Aggregated ' . $this->keys . ' keys'); - $queueForUsageDump + $queueForStatsUsageDump ->setStats($this->stats) ->trigger(); @@ -147,7 +152,11 @@ class Usage 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->getInternalId()], + METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS + ))); if (!empty($documents['value'])) { $metrics[] = [ @@ -180,24 +189,24 @@ class Usage 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))); - $buildsSuccess = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_SUCCESS))); - $buildsFailed = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_FAILED))); - $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))); - $buildsComputeSuccess = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE_SUCCESS))); - $buildsComputeFailed = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE_FAILED))); - $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))); + 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))); if (!empty($deployments['value'])) { $metrics[] = [ 'key' => METRIC_DEPLOYMENTS, 'value' => ($deployments['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_DEPLOYMENTS), + 'value' => ($deployments['value'] * -1), + ]; } if (!empty($deploymentsStorage['value'])) { @@ -205,6 +214,10 @@ class Usage extends Action 'key' => METRIC_DEPLOYMENTS_STORAGE, 'value' => ($deploymentsStorage['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_DEPLOYMENTS_STORAGE), + 'value' => ($deploymentsStorage['value'] * -1), + ]; } if (!empty($builds['value'])) { @@ -212,19 +225,9 @@ class Usage extends Action 'key' => METRIC_BUILDS, 'value' => ($builds['value'] * -1), ]; - } - - if (!empty($buildsSuccess['value'])) { $metrics[] = [ - 'key' => METRIC_BUILDS_SUCCESS, - 'value' => ($buildsSuccess['value'] * -1), - ]; - } - - if (!empty($buildsFailed['value'])) { - $metrics[] = [ - 'key' => METRIC_BUILDS_FAILED, - 'value' => ($buildsFailed['value'] * -1), + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_BUILDS), + 'value' => ($builds['value'] * -1), ]; } @@ -233,6 +236,10 @@ class Usage extends Action 'key' => METRIC_BUILDS_STORAGE, 'value' => ($buildsStorage['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_BUILDS_STORAGE), + 'value' => ($buildsStorage['value'] * -1), + ]; } if (!empty($buildsCompute['value'])) { @@ -240,19 +247,9 @@ class Usage extends Action 'key' => METRIC_BUILDS_COMPUTE, 'value' => ($buildsCompute['value'] * -1), ]; - } - - if (!empty($buildsComputeSuccess['value'])) { $metrics[] = [ - 'key' => METRIC_BUILDS_COMPUTE_SUCCESS, - 'value' => ($buildsComputeSuccess['value'] * -1), - ]; - } - - if (!empty($buildsComputeFailed['value'])) { - $metrics[] = [ - 'key' => METRIC_BUILDS_COMPUTE_FAILED, - 'value' => ($buildsComputeFailed['value'] * -1), + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_BUILDS_COMPUTE), + 'value' => ($buildsCompute['value'] * -1), ]; } @@ -261,6 +258,10 @@ class Usage extends Action 'key' => METRIC_EXECUTIONS, 'value' => ($executions['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_EXECUTIONS), + 'value' => ($executions['value'] * -1), + ]; } if (!empty($executionsCompute['value'])) { @@ -268,6 +269,10 @@ class Usage extends Action 'key' => METRIC_EXECUTIONS_COMPUTE, 'value' => ($executionsCompute['value'] * -1), ]; + $metrics[] = [ + 'key' => str_replace("{resourceType}", $document->getCollection(), METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), + 'value' => ($executionsCompute['value'] * -1), + ]; } break; default: diff --git a/src/Appwrite/Platform/Workers/UsageDump.php b/src/Appwrite/Platform/Workers/StatsUsageDump.php similarity index 54% rename from src/Appwrite/Platform/Workers/UsageDump.php rename to src/Appwrite/Platform/Workers/StatsUsageDump.php index b5480e1dec..119a9e7288 100644 --- a/src/Appwrite/Platform/Workers/UsageDump.php +++ b/src/Appwrite/Platform/Workers/StatsUsageDump.php @@ -7,18 +7,71 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\Exception\Duplicate; use Utopia\Platform\Action; use Utopia\Queue\Message; +use Utopia\Registry\Registry; use Utopia\System\System; -const METRIC_COLLECTION_LEVEL_STORAGE = 4; -const METRIC_DATABASE_LEVEL_STORAGE = 3; -const METRIC_PROJECT_LEVEL_STORAGE = 2; - -class UsageDump extends Action +class StatsUsageDump extends Action { + public const METRIC_COLLECTION_LEVEL_STORAGE = 4; + public const METRIC_DATABASE_LEVEL_STORAGE = 3; + public const METRIC_PROJECT_LEVEL_STORAGE = 2; protected array $stats = []; + + protected Registry $register; + + /** + * Metrics to skip writing to logsDB + * As these metrics are calculated separately + * by logs DB + * @var array + */ + protected array $skipBaseMetrics = [ + METRIC_DATABASES => 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 + */ + protected mixed $getLogsDB; + protected array $periods = [ '1h' => 'Y-m-d H:00', '1d' => 'Y-m-d 00:00', @@ -27,7 +80,7 @@ class UsageDump extends Action public static function getName(): string { - return 'usage-dump'; + return 'stats-usage-dump'; } /** @@ -38,37 +91,43 @@ class UsageDump extends Action $this ->inject('message') ->inject('getProjectDB') - ->callback(function (Message $message, callable $getProjectDB) { - $this->action($message, $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): void + 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'); } - // TODO: rename both usage workers @shimonewman foreach ($payload['stats'] ?? [] as $stats) { $project = new Document($stats['project'] ?? []); + $numberOfKeys = !empty($stats['keys']) ? count($stats['keys']) : 0; - $receivedAt = $stats['receivedAt'] ?? 'NONE'; + $receivedAt = $stats['receivedAt'] ?? null; if ($numberOfKeys === 0) { continue; } - console::log('[' . DateTime::now() . '] ProjectId [' . $project->getInternalId() . '] ReceivedAt [' . $receivedAt . '] ' . $numberOfKeys . ' keys'); + console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); try { + /** @var \Utopia\Database\Database $dbForProject */ $dbForProject = $getProjectDB($project); foreach ($stats['keys'] ?? [] as $key => $value) { if ($value == 0) { @@ -77,7 +136,7 @@ class UsageDump extends Action if (str_contains($key, METRIC_DATABASES_STORAGE)) { try { - $this->handleDatabaseStorage($key, $dbForProject); + $this->handleDatabaseStorage($key, $dbForProject, $project, $receivedAt); } catch (\Exception $e) { console::error('[' . DateTime::now() . '] failed to calculate database storage for key [' . $key . '] ' . $e->getMessage()); } @@ -85,35 +144,31 @@ class UsageDump extends Action } foreach ($this->periods as $period => $format) { - $time = 'inf' === $period ? null : date($format, time()); + $time = null; + + if ($period !== 'inf') { + $time = !empty($receivedAt) ? (new \DateTime($receivedAt))->format($format) : date($format, time()); + } $id = \md5("{$time}_{$period}_{$key}"); - try { - $dbForProject->createDocument('stats', new Document([ - '$id' => $id, - 'period' => $period, - 'time' => $time, - 'metric' => $key, - 'value' => $value, - 'region' => System::getEnv('_APP_REGION', 'default'), - ])); - } catch (Duplicate $th) { - if ($value < 0) { - $dbForProject->decreaseDocumentAttribute( - 'stats', - $id, - 'value', - abs($value) - ); - } else { - $dbForProject->increaseDocumentAttribute( - 'stats', - $id, - 'value', - $value - ); - } - } + $document = new Document([ + '$id' => $id, + 'period' => $period, + 'time' => $time, + 'metric' => $key, + 'value' => $value, + 'region' => System::getEnv('_APP_REGION', 'default'), + ]); + + $documentClone = new Document($document->getArrayCopy()); + + $dbForProject->createOrUpdateDocumentsWithIncrease( + 'stats', + 'value', + [$document] + ); + + $this->writeToLogsDB($project, $documentClone); } } } catch (\Exception $e) { @@ -122,44 +177,37 @@ class UsageDump extends Action } } - private function handleDatabaseStorage(string $key, Database $dbForProject): void + private function handleDatabaseStorage(string $key, Database $dbForProject, Document $project, string $receivedAt): void { $data = explode('.', $key); $start = microtime(true); - $updateMetric = function (Database $dbForProject, int $value, string $key, string $period, string|null $time) { + $updateMetric = function (Database $dbForProject, Document $project, int $value, string $key, string $period, string|null $time) use ($receivedAt) { $id = \md5("{$time}_{$period}_{$key}"); - try { - $dbForProject->createDocument('stats', new Document([ - '$id' => $id, - 'period' => $period, - 'time' => $time, - 'metric' => $key, - 'value' => $value, - 'region' => System::getEnv('_APP_REGION', 'default'), - ])); - } catch (Duplicate $th) { - if ($value < 0) { - $dbForProject->decreaseDocumentAttribute( - 'stats', - $id, - 'value', - abs($value) - ); - } else { - $dbForProject->increaseDocumentAttribute( - 'stats', - $id, - 'value', - $value - ); - } - } + $document = new Document([ + '$id' => $id, + 'period' => $period, + 'time' => $time, + 'metric' => $key, + 'value' => $value, + 'region' => System::getEnv('_APP_REGION', 'default'), + ]); + $documentClone = new Document($document->getArrayCopy()); + $dbForProject->createOrUpdateDocumentsWithIncrease( + 'stats', + 'value', + [$document] + ); + $this->writeToLogsDB($project, $documentClone); }; foreach ($this->periods as $period => $format) { - $time = 'inf' === $period ? null : date($format, time()); + $time = null; + + if ($period !== 'inf') { + $time = !empty($receivedAt) ? (new \DateTime($receivedAt))->format($format) : date($format, time()); + } $id = \md5("{$time}_{$period}_{$key}"); $value = 0; @@ -172,7 +220,7 @@ class UsageDump extends Action switch (count($data)) { // Collection Level - case METRIC_COLLECTION_LEVEL_STORAGE: + case self::METRIC_COLLECTION_LEVEL_STORAGE: Console::log('[' . DateTime::now() . '] Collection Level Storage Calculation [' . $key . ']'); $databaseInternalId = $data[0]; $collectionInternalId = $data[1]; @@ -194,18 +242,18 @@ class UsageDump extends Action } // Update Collection - $updateMetric($dbForProject, $diff, $key, $period, $time); + $updateMetric($dbForProject, $project, $diff, $key, $period, $time); // Update Database $databaseKey = str_replace(['{databaseInternalId}'], [$data[0]], METRIC_DATABASE_ID_STORAGE); - $updateMetric($dbForProject, $diff, $databaseKey, $period, $time); + $updateMetric($dbForProject, $project, $diff, $databaseKey, $period, $time); // Update Project $projectKey = METRIC_DATABASES_STORAGE; - $updateMetric($dbForProject, $diff, $projectKey, $period, $time); + $updateMetric($dbForProject, $project, $diff, $projectKey, $period, $time); break; // Database Level - case METRIC_DATABASE_LEVEL_STORAGE: + case self::METRIC_DATABASE_LEVEL_STORAGE: Console::log('[' . DateTime::now() . '] Database Level Storage Calculation [' . $key . ']'); $databaseInternalId = $data[0]; @@ -238,14 +286,14 @@ class UsageDump extends Action // Update Database $databaseKey = str_replace(['{databaseInternalId}'], [$data[0]], METRIC_DATABASE_ID_STORAGE); - $updateMetric($dbForProject, $diff, $databaseKey, $period, $time); + $updateMetric($dbForProject, $project, $diff, $databaseKey, $period, $time); // Update Project $projectKey = METRIC_DATABASES_STORAGE; - $updateMetric($dbForProject, $diff, $projectKey, $period, $time); + $updateMetric($dbForProject, $project, $diff, $projectKey, $period, $time); break; // Project Level - case METRIC_PROJECT_LEVEL_STORAGE: + case self::METRIC_PROJECT_LEVEL_STORAGE: Console::log('[' . DateTime::now() . '] Project Level Storage Calculation [' . $key . ']'); // Get all project databases $databases = $dbForProject->find('database'); @@ -270,7 +318,7 @@ class UsageDump extends Action // Update Project $projectKey = METRIC_DATABASES_STORAGE; - $updateMetric($dbForProject, $diff, $projectKey, $period, $time); + $updateMetric($dbForProject, $project, $diff, $projectKey, $period, $time); break; } } @@ -279,4 +327,37 @@ class UsageDump extends Action console::log('[' . DateTime::now() . '] DB Storage Calculation [' . $key . '] took ' . (($end - $start) * 1000) . ' milliseconds'); } + + 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; + } + } + + /** @var \Utopia\Database\Database $dbForLogs*/ + $dbForLogs = call_user_func($this->getLogsDB, $project); + + try { + $dbForLogs->createOrUpdateDocumentsWithIncrease( + 'stats', + 'value', + [$document] + ); + Console::success('Usage logs pushed to Logs DB'); + } catch (\Throwable $th) { + Console::error($th->getMessage()); + } + + $this->register->get('pools')->get('logs')->reclaim(); + } } diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index 88ca7871f2..2066f690ac 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Workers; use Appwrite\Event\Mail; +use Appwrite\Event\StatsUsage; use Appwrite\Template\Template; use Exception; use Utopia\Database\Database; @@ -31,21 +32,24 @@ class Webhooks extends Action $this ->desc('Webhooks worker') ->inject('message') - ->inject('dbForConsole') + ->inject('project') + ->inject('dbForPlatform') ->inject('queueForMails') + ->inject('queueForStatsUsage') ->inject('log') - ->callback(fn (Message $message, Database $dbForConsole, Mail $queueForMails, Log $log) => $this->action($message, $dbForConsole, $queueForMails, $log)); + ->callback([$this, 'action']); } /** * @param Message $message - * @param Database $dbForConsole + * @param Document $project + * @param Database $dbForPlatform * @param Mail $queueForMails * @param Log $log * @return void * @throws Exception */ - public function action(Message $message, Database $dbForConsole, Mail $queueForMails, Log $log): void + public function action(Message $message, Document $project, Database $dbForPlatform, Mail $queueForMails, StatsUsage $queueForStatsUsage, Log $log): void { $this->errors = []; $payload = $message->getPayload() ?? []; @@ -56,14 +60,13 @@ class Webhooks extends Action $events = $payload['events']; $webhookPayload = json_encode($payload['payload']); - $project = new Document($payload['project']); $user = new Document($payload['user'] ?? []); $log->addTag('projectId', $project->getId()); foreach ($project->getAttribute('webhooks', []) as $webhook) { if (array_intersect($webhook->getAttribute('events', []), $events)) { - $this->execute($events, $webhookPayload, $webhook, $user, $project, $dbForConsole, $queueForMails); + $this->execute($events, $webhookPayload, $webhook, $user, $project, $dbForPlatform, $queueForMails, $queueForStatsUsage); } } @@ -78,11 +81,11 @@ class Webhooks extends Action * @param Document $webhook * @param Document $user * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Mail $queueForMails * @return void */ - private function execute(array $events, string $payload, Document $webhook, Document $user, Document $project, Database $dbForConsole, Mail $queueForMails): void + private function execute(array $events, string $payload, Document $webhook, Document $user, Document $project, Database $dbForPlatform, Mail $queueForMails, StatsUsage $queueForStatsUsage): void { if ($webhook->getAttribute('enabled') !== true) { return; @@ -138,8 +141,8 @@ class Webhooks extends Action \curl_close($ch); if (!empty($curlError) || $statusCode >= 400) { - $dbForConsole->increaseDocumentAttribute('webhooks', $webhook->getId(), 'attempts', 1); - $webhook = $dbForConsole->getDocument('webhooks', $webhook->getId()); + $dbForPlatform->increaseDocumentAttribute('webhooks', $webhook->getId(), 'attempts', 1); + $webhook = $dbForPlatform->getDocument('webhooks', $webhook->getId()); $attempts = $webhook->getAttribute('attempts'); $logs = ''; @@ -158,18 +161,32 @@ class Webhooks extends Action if ($attempts >= \intval(System::getEnv('_APP_WEBHOOK_MAX_FAILED_ATTEMPTS', '10'))) { $webhook->setAttribute('enabled', false); - $this->sendEmailAlert($attempts, $statusCode, $webhook, $project, $dbForConsole, $queueForMails); + $this->sendEmailAlert($attempts, $statusCode, $webhook, $project, $dbForPlatform, $queueForMails); } - $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $this->errors[] = $logs; + $queueForStatsUsage + ->addMetric(METRIC_WEBHOOKS_FAILED, 1) + ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_FAILED), 1) + ; + + } else { $webhook->setAttribute('attempts', 0); // Reset attempts on success - $dbForConsole->updateDocument('webhooks', $webhook->getId(), $webhook); - $dbForConsole->purgeCachedDocument('projects', $project->getId()); + $dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook); + $dbForPlatform->purgeCachedDocument('projects', $project->getId()); + $queueForStatsUsage + ->addMetric(METRIC_WEBHOOKS_SENT, 1) + ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_SENT), 1) + ; } + + $queueForStatsUsage + ->setProject($project) + ->trigger(); } /** @@ -177,20 +194,20 @@ class Webhooks extends Action * @param mixed $statusCode * @param Document $webhook * @param Document $project - * @param Database $dbForConsole + * @param Database $dbForPlatform * @param Mail $queueForMails * @return void */ - public function sendEmailAlert(int $attempts, mixed $statusCode, Document $webhook, Document $project, Database $dbForConsole, Mail $queueForMails): void + public function sendEmailAlert(int $attempts, mixed $statusCode, Document $webhook, Document $project, Database $dbForPlatform, Mail $queueForMails): void { - $memberships = $dbForConsole->find('memberships', [ + $memberships = $dbForPlatform->find('memberships', [ Query::equal('teamInternalId', [$project->getAttribute('teamInternalId')]), Query::limit(APP_LIMIT_SUBQUERY) ]); $userIds = array_column(\array_map(fn ($membership) => $membership->getArrayCopy(), $memberships), 'userId'); - $users = $dbForConsole->find('users', [ + $users = $dbForPlatform->find('users', [ Query::equal('$id', $userIds), ]); diff --git a/src/Appwrite/SDK/AuthType.php b/src/Appwrite/SDK/AuthType.php new file mode 100644 index 0000000000..307b3cf35e --- /dev/null +++ b/src/Appwrite/SDK/AuthType.php @@ -0,0 +1,11 @@ +<?php + +namespace Appwrite\SDK; + +enum AuthType: string +{ + case JWT = APP_AUTH_TYPE_JWT; + case KEY = APP_AUTH_TYPE_KEY; + case SESSION = APP_AUTH_TYPE_SESSION; + case ADMIN = APP_AUTH_TYPE_ADMIN; +} diff --git a/src/Appwrite/SDK/ContentType.php b/src/Appwrite/SDK/ContentType.php new file mode 100644 index 0000000000..174c889815 --- /dev/null +++ b/src/Appwrite/SDK/ContentType.php @@ -0,0 +1,15 @@ +<?php + +namespace Appwrite\SDK; + +enum ContentType: string +{ + case NONE = ''; + case JSON = 'application/json'; + case IMAGE = 'image/*'; + case IMAGE_PNG = 'image/png'; + case MULTIPART = 'multipart/form-data'; + case HTML = 'text/html'; + case TEXT = 'text/plain'; + case ANY = '*/*'; +} diff --git a/src/Appwrite/SDK/Method.php b/src/Appwrite/SDK/Method.php new file mode 100644 index 0000000000..9b22b10004 --- /dev/null +++ b/src/Appwrite/SDK/Method.php @@ -0,0 +1,288 @@ +<?php + +namespace Appwrite\SDK; + +use Appwrite\SDK\Response as SDKResponse; +use Appwrite\Utopia\Response; +use Swoole\Http\Response as HttpResponse; + +class Method +{ + public static array $processed = []; + + public static array $errors = []; + + /** + * Initialise a new SDK method + * + * @param string $namespace + * @param string $name + * @param string $description + * @param array<AuthType> $auth + * @param array<SDKResponse> $responses + * @param ContentType $responseType + * @param MethodType|null $methodType + * @param bool $deprecated + * @param array|bool $hide + * @param bool $packaging + * @param string $requestType + * @param array $parameters + * @param array $additionalParameters + * + * @throws \Exception + */ + public function __construct( + protected string $namespace, + protected string $name, + protected string $description, + protected array $auth, + protected array $responses, + protected ContentType $contentType = ContentType::JSON, + protected ?MethodType $type = null, + protected bool $deprecated = false, + protected array|bool $hide = false, + protected bool $packaging = false, + protected string $requestType = 'application/json', + protected array $parameters = [], + protected array $additionalParameters = [] + ) { + $this->validateMethod($name, $namespace); + $this->validateAuthTypes($auth); + $this->validateDesc($description); + + foreach ($responses as $response) { + /** @var SDKResponse $response */ + $this->validateResponseModel($response->getModel()); + $this->validateNoContent($response); + } + } + + protected function getRouteName(): string + { + return $this->namespace . '.' . $this->name; + } + + protected function validateMethod(string $name, string $namespace): void + { + if (\in_array($this->getRouteName(), self::$processed)) { + self::$errors[] = "Error with {$this->getRouteName()} method: Method already exists in namespace {$namespace}"; + } + + self::$processed[] = $this->getRouteName(); + } + + protected function validateAuthTypes(array $authTypes): void + { + foreach ($authTypes as $authType) { + if (!($authType instanceof AuthType)) { + self::$errors[] = "Error with {$this->getRouteName()} method: Invalid auth type"; + } + } + } + + protected function validateDesc(string $desc): void + { + if (empty($desc)) { + self::$errors[] = "Error with {$this->getRouteName()} method: Description label is empty"; + return; + } + + if (\str_ends_with($desc, '.md')) { + $descPath = $this->getDescriptionFilePath() ?: $this->getDescription(); + + if (empty($descPath)) { + self::$errors[] = "Error with {$this->getRouteName()} method: Description file not found at {$desc}"; + return; + } + } + } + + protected function validateResponseModel(string|array $responseModel): void + { + $response = new Response(new HttpResponse()); + + if (!\is_array($responseModel)) { + $responseModel = [$responseModel]; + } + + foreach ($responseModel as $model) { + try { + $response->getModel($model); + } catch (\Exception $e) { + self::$errors[] = "Error with {$this->getRouteName()} method: Invalid response model, make sure the model has been defined in Response.php"; + } + } + } + + protected function validateNoContent(SDKResponse $response): void + { + if ($response->getCode() === 204) { + if ($response->getModel() !== Response::MODEL_NONE) { + self::$errors[] = "Error with {$this->getRouteName()} method: Response code 204 must have response model 'none'"; + } + } + } + + public function getNamespace(): string + { + return $this->namespace; + } + + public function getMethodName(): string + { + return $this->name; + } + + public function getDescription(): string + { + return $this->description; + } + + /** + * This method returns the absolute path to the description file returning null if the file does not exist. + * + * @return string|null + */ + public function getDescriptionFilePath(): ?string + { + return \realpath(__DIR__ . '/../../../' . $this->getDescription()) ?: null; + } + + public function getAuth(): array + { + return $this->auth; + } + + /** + * @return array<SDKResponse> + */ + public function getResponses(): array + { + return $this->responses; + } + + public function getContentType(): ContentType + { + return $this->contentType; + } + + public function getType(): ?MethodType + { + return $this->type; + } + + public function isDeprecated(): bool + { + return $this->deprecated; + } + + public function isHidden(): bool|array + { + return $this->hide ?? false; + } + + public function isPackaging(): bool + { + return $this->packaging; + } + + public function getRequestType(): string + { + return $this->requestType; + } + + public function getParameters(): array + { + return $this->parameters; + } + + public function getAdditionalParameters(): array + { + return $this->additionalParameters; + } + + public function setNamespace(string $namespace): self + { + $this->namespace = $namespace; + return $this; + } + + public function setMethodName(string $name): self + { + $this->name = $name; + return $this; + } + + public function setDescription(string $description): self + { + $this->description = $description; + return $this; + } + + public function setAuth(array $auth): self + { + $this->validateAuthTypes($auth); + $this->auth = $auth; + return $this; + } + + /** + * @param array<SDKResponse> $responses + */ + public function setResponses(array $responses): self + { + foreach ($responses as $response) { + $this->validateResponseModel($response->getModel()); + $this->validateNoContent($response); + } + $this->responses = $responses; + return $this; + } + + public function setContentType(ContentType $contentType): self + { + $this->contentType = $contentType; + return $this; + } + + public function setType(?MethodType $type): self + { + $this->type = $type; + return $this; + } + + public function setDeprecated(bool $deprecated): self + { + $this->deprecated = $deprecated; + return $this; + } + + public function setHide(bool|array $hide): self + { + $this->hide = $hide; + return $this; + } + + public function setPackaging(bool $packaging): self + { + $this->packaging = $packaging; + return $this; + } + + public function setRequestType(string $requestType): self + { + $this->requestType = $requestType; + return $this; + } + + public function setParameters(array $parameters): self + { + $this->parameters = $parameters; + return $this; + } + + public static function getErrors(): array + { + return self::$errors; + } +} diff --git a/src/Appwrite/SDK/MethodType.php b/src/Appwrite/SDK/MethodType.php new file mode 100644 index 0000000000..2b1f786779 --- /dev/null +++ b/src/Appwrite/SDK/MethodType.php @@ -0,0 +1,11 @@ +<?php + +namespace Appwrite\SDK; + +enum MethodType: string +{ + case WEBAUTH = 'webAuth'; + case LOCATION = 'location'; + case GRAPHQL = 'graphql'; + case UPLOAD = 'upload'; +} diff --git a/src/Appwrite/SDK/Response.php b/src/Appwrite/SDK/Response.php new file mode 100644 index 0000000000..e87813024b --- /dev/null +++ b/src/Appwrite/SDK/Response.php @@ -0,0 +1,27 @@ +<?php + +namespace Appwrite\SDK; + +class Response +{ + /** + * @param int $code + * @param string|array $model + * @param string $description + */ + public function __construct( + private int $code, + private string|array $model + ) { + } + + public function getCode(): int + { + return $this->code; + } + + public function getModel(): string|array + { + return $this->model; + } +} diff --git a/src/Appwrite/Specification/Format.php b/src/Appwrite/Specification/Format.php index 30ce6470e1..2e7db7e8a5 100644 --- a/src/Appwrite/Specification/Format.php +++ b/src/Appwrite/Specification/Format.php @@ -113,6 +113,18 @@ abstract class Format protected function getEnumName(string $service, string $method, string $param): ?string { switch ($service) { + case 'console': + switch ($method) { + case 'getResource': + switch ($param) { + case 'type': + return 'ConsoleResourceType'; + case 'value': + return 'ConsoleResourceValue'; + } + break; + } + break; case 'account': switch ($method) { case 'createOAuth2Session': @@ -184,7 +196,7 @@ abstract class Format case 'functions': switch ($method) { case 'getUsage': - case 'getFunctionUsage': + case 'listUsage': switch ($param) { case 'range': return 'FunctionUsageRange'; @@ -196,6 +208,52 @@ abstract class Format return 'ExecutionMethod'; } break; + case 'getDeploymentDownload': + switch ($param) { + case 'type': + return 'DeploymentDownloadType'; + } + break; + case 'createVcsDeployment': + switch ($param) { + case 'type': + return 'VCSDeploymentType'; + } + break; + } + break; + case 'sites': + switch ($method) { + case 'getDeploymentDownload': + switch ($param) { + case 'type': + return 'DeploymentDownloadType'; + } + break; + case 'getUsage': + case 'listUsage': + switch ($param) { + case 'range': + return 'SiteUsageRange'; + } + break; + case 'createVcsDeployment': + switch ($param) { + case 'type': + return 'VCSDeploymentType'; + } + break; + } + break; + case 'vcs': + switch ($method) { + case 'createRepositoryDetection': + case 'listRepositories': + switch ($param) { + case 'type': + return 'VCSDetectionType'; + } + break; } break; case 'messaging': @@ -215,6 +273,8 @@ abstract class Format switch ($param) { case 'status': return 'MessageStatus'; + case 'priority': + return 'MessagePriority'; } break; case 'createSmtpProvider': @@ -378,10 +438,24 @@ abstract class Format return ['Twenty Four Hours', 'Thirty Days', 'Ninety Days']; } break; + case 'proxy': + switch ($method) { + case 'createRedirectRule': + return ['Moved Permanently 301', 'Found 302', 'Temporary Redirect 307', 'Permanent Redirect 308']; + } + break; case 'functions': switch ($method) { case 'getUsage': - case 'getFunctionUsage': + case 'listUsage': + // Range Enum Keys + return ['Twenty Four Hours', 'Thirty Days', 'Ninety Days']; + } + break; + case 'sites': + switch ($method) { + case 'getUsage': + case 'listUsage': // Range Enum Keys return ['Twenty Four Hours', 'Thirty Days', 'Ninety Days']; } diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index f7430ec70e..864caed4e1 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -2,6 +2,8 @@ namespace Appwrite\Specification\Format; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\MethodType; use Appwrite\Specification\Format; use Appwrite\Template\Template; use Appwrite\Utopia\Response\Model; @@ -120,28 +122,49 @@ class OpenAPI3 extends Format foreach ($this->routes as $route) { $url = \str_replace('/v1', '', $route->getPath()); $scope = $route->getLabel('scope', ''); - $consumes = [$route->getLabel('sdk.request.type', 'application/json')]; + $sdk = $route->getLabel('sdk', false); - $method = $route->getLabel('sdk.method', \uniqid()); - $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null; - $produces = $route->getLabel('sdk.response.type', null); - $model = $route->getLabel('sdk.response.model', 'none'); - $routeSecurity = $route->getLabel('sdk.auth', []); + if (empty($sdk)) { + continue; + } + + $additionalMethods = null; + if (is_array($sdk)) { + $mainSdk = array_shift($sdk); + $additionalMethods = $sdk; + + $sdk = $mainSdk; + } + + /** + * @var \Appwrite\SDK\Method $sdk + */ + $consumes = [$sdk->getRequestType()]; + + $method = $sdk->getMethodName() ?? \uniqid(); + + if (!empty($method) && is_array($method)) { + $method = array_keys($method)[0]; + } + + $desc = $sdk->getDescriptionFilePath() ?: $sdk->getDescription(); + $produces = ($sdk->getContentType())->value; + $routeSecurity = $sdk->getAuth() ?? []; $sdkPlatforms = []; foreach ($routeSecurity as $value) { switch ($value) { - case APP_AUTH_TYPE_SESSION: + case AuthType::SESSION: $sdkPlatforms[] = APP_PLATFORM_CLIENT; break; - case APP_AUTH_TYPE_KEY: + case AuthType::KEY: $sdkPlatforms[] = APP_PLATFORM_SERVER; break; - case APP_AUTH_TYPE_JWT: + case AuthType::JWT: $sdkPlatforms[] = APP_PLATFORM_SERVER; break; - case APP_AUTH_TYPE_ADMIN: + case AuthType::ADMIN: $sdkPlatforms[] = APP_PLATFORM_CONSOLE; break; } @@ -152,102 +175,143 @@ class OpenAPI3 extends Format $sdkPlatforms[] = APP_PLATFORM_CLIENT; } + $namespace = $sdk->getNamespace() ?? 'default'; + + $desc ??= ''; + $descContents = \str_ends_with($desc, '.md') ? \file_get_contents($desc) : $desc; + $temp = [ 'summary' => $route->getDesc(), - 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($method), - 'tags' => [$route->getLabel('sdk.namespace', 'default')], - 'description' => ($desc) ? \file_get_contents($desc) : '', + 'operationId' => $namespace . ucfirst($method), + 'tags' => [$namespace], + 'description' => $descContents, 'responses' => [], 'x-appwrite' => [ // Appwrite related metadata 'method' => $method, 'weight' => $route->getOrder(), 'cookies' => $route->getLabel('sdk.cookies', false), - 'type' => $route->getLabel('sdk.methodType', ''), - 'deprecated' => $route->getLabel('sdk.deprecated', false), - 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($method) . '.md', - 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''), + 'type' => $sdk->getType()->value ?? '', + 'deprecated' => $sdk->isDeprecated(), + 'demo' => Template::fromCamelCaseToDash($namespace) . '/' . Template::fromCamelCaseToDash($method) . '.md', + 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $sdk->getDescription() ?? '', 'rate-limit' => $route->getLabel('abuse-limit', 0), 'rate-time' => $route->getLabel('abuse-time', 3600), 'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'), 'scope' => $route->getLabel('scope', ''), 'platforms' => $sdkPlatforms, - 'packaging' => $route->getLabel('sdk.packaging', false), - 'offline-model' => $route->getLabel('sdk.offline.model', ''), - 'offline-key' => $route->getLabel('sdk.offline.key', ''), - 'offline-response-key' => $route->getLabel('sdk.offline.response.key', '$id'), + 'packaging' => $sdk->isPackaging() ], ]; - foreach ($this->models as $value) { - if (\is_array($model)) { - $model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model); - } else { - if ($value->getType() === $model) { - $model = $value; - break; + + if (!empty($additionalMethods)) { + $temp['x-appwrite']['additional-methods'] = []; + foreach ($additionalMethods as $method) { + /** @var \Appwrite\SDK\Method $method */ + $additionalMethod = [ + 'name' => $method->getMethodName(), + 'parameters' => [], + 'required' => [], + 'responses' => [] + ]; + + foreach ($method->getParameters() as $name => $param) { + $additionalMethod['parameters'][] = $name; + + if (!$param['optional']) { + $additionalMethod['required'][] = $name; + } } + + foreach ($method->getResponses() as $response) { + /** @var \Appwrite\SDK\Response $response */ + $additionalMethod['responses'][] = [ + 'code' => $response->getCode(), + 'model' => '#/components/schemas/' . $response->getModel() + ]; + } + + $temp['x-appwrite']['additional-methods'][] = $additionalMethod; } } - if (!(\is_array($model)) && $model->isNone()) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => in_array($produces, [ - 'image/*', - 'image/jpeg', - 'image/gif', - 'image/png', - 'image/webp', - 'image/svg-x', - 'image/x-icon', - 'image/bmp', - ]) ? 'Image' : 'File', - ]; - } else { - if (\is_array($model)) { - $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); + // Handle response models + foreach ($sdk->getResponses() as $response) { + /** @var \Appwrite\SDK\Response $response */ + $model = $response->getModel(); - // model has multiple possible responses, we will use oneOf - foreach ($model as $m) { - $usedModels[] = $m->getType(); + foreach ($this->models as $value) { + if (\is_array($model)) { + $model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model); + } else { + if ($value->getType() === $model) { + $model = $value; + break; + } } + } - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => $modelDescription, - 'content' => [ - $produces => [ - 'schema' => [ - 'oneOf' => \array_map(fn ($m) => ['$ref' => '#/components/schemas/' . $m->getType()], $model) - ], - ], - ], + if (!(\is_array($model)) && $model->isNone()) { + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => in_array($produces, [ + 'image/*', + 'image/jpeg', + 'image/gif', + 'image/png', + 'image/webp', + 'image/svg-x', + 'image/x-icon', + 'image/bmp', + ]) ? 'Image' : 'File', ]; } else { - // Response definition using one type - $usedModels[] = $model->getType(); - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => $model->getName(), - 'content' => [ - $produces => [ - 'schema' => [ - '$ref' => '#/components/schemas/' . $model->getType(), + if (\is_array($model)) { + $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); + + // model has multiple possible responses, we will use oneOf + foreach ($model as $m) { + $usedModels[] = $m->getType(); + } + + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => $modelDescription, + 'content' => [ + $produces => [ + 'schema' => [ + 'oneOf' => \array_map(fn ($m) => ['$ref' => '#/components/schemas/' . $m->getType()], $model) + ], ], ], - ], - ]; + ]; + } else { + // Response definition using one type + $usedModels[] = $model->getType(); + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => $model->getName(), + 'content' => [ + $produces => [ + 'schema' => [ + '$ref' => '#/components/schemas/' . $model->getType(), + ], + ], + ], + ]; + } } - } - if ($route->getLabel('sdk.response.code', 500) === 204) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; - unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']); + if (($response->getCode() ?? 500) === 204) { + $temp['responses'][(string)$response->getCode() ?? '500']['description'] = 'No content'; + unset($temp['responses'][(string)$response->getCode() ?? '500']['schema']); + } } if ((!empty($scope))) { // && 'public' != $scope $securities = ['Project' => []]; - foreach ($route->getLabel('sdk.auth', []) as $security) { - if (array_key_exists($security, $this->keys)) { - $securities[$security] = []; + foreach ($sdk->getAuth() as $security) { + /** @var \Appwrite\SDK\AuthType $security */ + if (array_key_exists($security->value, $this->keys)) { + $securities[$security->value] = []; } } @@ -298,7 +362,7 @@ class OpenAPI3 extends Format $node['schema']['x-example'] = false; break; case 'Appwrite\Utopia\Database\Validator\CustomId': - if ($route->getLabel('sdk.methodType', '') === 'upload') { + if ($sdk->getType() === MethodType::UPLOAD) { $node['schema']['x-upload-id'] = true; } $node['schema']['type'] = $validator->getType(); @@ -422,7 +486,7 @@ class OpenAPI3 extends Format $allowed = true; foreach ($this->enumBlacklist as $blacklist) { if ( - $blacklist['namespace'] == $route->getLabel('sdk.namespace', '') + $blacklist['namespace'] == $sdk->getNamespace() && $blacklist['method'] == $method && $blacklist['parameter'] == $name ) { @@ -433,8 +497,8 @@ class OpenAPI3 extends Format if ($allowed) { $node['schema']['enum'] = $validator->getList(); - $node['schema']['x-enum-name'] = $this->getEnumName($route->getLabel('sdk.namespace', ''), $method, $name); - $node['schema']['x-enum-keys'] = $this->getEnumKeys($route->getLabel('sdk.namespace', ''), $method, $name); + $node['schema']['x-enum-name'] = $this->getEnumName($sdk->getNamespace() ?? '', $method, $name); + $node['schema']['x-enum-keys'] = $this->getEnumKeys($sdk->getNamespace() ?? '', $method, $name); } if ($validator->getType() === 'integer') { $node['format'] = 'int32'; diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index f2e324c71f..3a7889275e 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -2,6 +2,8 @@ namespace Appwrite\Specification\Format; +use Appwrite\SDK\AuthType; +use Appwrite\SDK\MethodType; use Appwrite\Specification\Format; use Appwrite\Template\Template; use Appwrite\Utopia\Response\Model; @@ -118,27 +120,47 @@ class Swagger2 extends Format /** @var \Utopia\Route $route */ $url = \str_replace('/v1', '', $route->getPath()); $scope = $route->getLabel('scope', ''); - $consumes = [$route->getLabel('sdk.request.type', 'application/json')]; - $method = $route->getLabel('sdk.method', \uniqid()); - $desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null; - $produces = $route->getLabel('sdk.response.type', null); - $model = $route->getLabel('sdk.response.model', 'none'); - $routeSecurity = $route->getLabel('sdk.auth', []); + /** @var \Appwrite\SDK\Method $sdk */ + $sdk = $route->getLabel('sdk', false); + + if (empty($sdk)) { + continue; + } + + $additionalMethods = null; + if (is_array($sdk)) { + $mainSdk = array_shift($sdk); + $additionalMethods = $sdk; + + $sdk = $mainSdk; + } + + $consumes = [$sdk->getRequestType()]; + + $method = $sdk->getMethodName() ?? \uniqid(); + + if (!empty($method) && is_array($method)) { + $method = array_keys($method)[0]; + } + + $desc = $sdk->getDescriptionFilePath() ?: $sdk->getDescription(); + $produces = ($sdk->getContentType())->value; + $routeSecurity = $sdk->getAuth() ?? []; $sdkPlatforms = []; foreach ($routeSecurity as $value) { switch ($value) { - case APP_AUTH_TYPE_SESSION: + case AuthType::SESSION: $sdkPlatforms[] = APP_PLATFORM_CLIENT; break; - case APP_AUTH_TYPE_KEY: + case AuthType::KEY: $sdkPlatforms[] = APP_PLATFORM_SERVER; break; - case APP_AUTH_TYPE_JWT: + case AuthType::JWT: $sdkPlatforms[] = APP_PLATFORM_SERVER; break; - case APP_AUTH_TYPE_ADMIN: + case AuthType::ADMIN: $sdkPlatforms[] = APP_PLATFORM_CONSOLE; break; } @@ -149,31 +171,33 @@ class Swagger2 extends Format $sdkPlatforms[] = APP_PLATFORM_CLIENT; } + $namespace = $sdk->getNamespace() ?? 'default'; + + $desc ??= ''; + $descContents = \str_ends_with($desc, '.md') ? \file_get_contents($desc) : $desc; + $temp = [ 'summary' => $route->getDesc(), - 'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($method), + 'operationId' => $namespace . ucfirst($method), 'consumes' => [], 'produces' => [], - 'tags' => [$route->getLabel('sdk.namespace', 'default')], - 'description' => ($desc) ? \file_get_contents($desc) : '', + 'tags' => [$namespace], + 'description' => $descContents, 'responses' => [], 'x-appwrite' => [ // Appwrite related metadata 'method' => $method, 'weight' => $route->getOrder(), 'cookies' => $route->getLabel('sdk.cookies', false), - 'type' => $route->getLabel('sdk.methodType', ''), - 'deprecated' => $route->getLabel('sdk.deprecated', false), - 'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($method) . '.md', - 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''), + 'type' => $sdk->getType()->value ?? '', + 'deprecated' => $sdk->isDeprecated(), + 'demo' => Template::fromCamelCaseToDash($namespace) . '/' . Template::fromCamelCaseToDash($method) . '.md', + 'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $sdk->getDescription() ?? '', 'rate-limit' => $route->getLabel('abuse-limit', 0), 'rate-time' => $route->getLabel('abuse-time', 3600), 'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'), 'scope' => $route->getLabel('scope', ''), 'platforms' => $sdkPlatforms, - 'packaging' => $route->getLabel('sdk.packaging', false), - 'offline-model' => $route->getLabel('sdk.offline.model', ''), - 'offline-key' => $route->getLabel('sdk.offline.key', ''), - 'offline-response-key' => $route->getLabel('sdk.offline.response.key', '$id'), + 'packaging' => $sdk->isPackaging() ], ]; @@ -181,71 +205,111 @@ class Swagger2 extends Format $temp['produces'][] = $produces; } - foreach ($this->models as $value) { - if (\is_array($model)) { - $model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model); - } else { - if ($value->getType() === $model) { - $model = $value; - break; + if (!empty($additionalMethods)) { + $temp['x-appwrite']['additional-methods'] = []; + foreach ($additionalMethods as $method) { + /** @var \Appwrite\SDK\Method $method */ + $additionalMethod = [ + 'name' => $method->getMethodName(), + 'parameters' => [], + 'required' => [], + 'responses' => [], + 'description' => $method->getDescription(), + ]; + + foreach ($method->getParameters() as $name => $param) { + $additionalMethod['parameters'][] = $name; + + if (!$param['optional']) { + $additionalMethod['required'][] = $name; + } } + + foreach ($method->getResponses() as $response) { + /** @var \Appwrite\SDK\Response $response */ + $additionalMethod['responses'][] = [ + 'code' => $response->getCode(), + 'model' => '#/definitions/' . $response->getModel() + ]; + } + + $temp['x-appwrite']['additional-methods'][] = $additionalMethod; } } - if (!(\is_array($model)) && $model->isNone()) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => in_array($produces, [ - 'image/*', - 'image/jpeg', - 'image/gif', - 'image/png', - 'image/webp', - 'image/svg-x', - 'image/x-icon', - 'image/bmp', - ]) ? 'Image' : 'File', - 'schema' => [ - 'type' => 'file' - ], - ]; - } else { - if (\is_array($model)) { - $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); - // model has multiple possible responses, we will use oneOf - foreach ($model as $m) { - $usedModels[] = $m->getType(); + // Handle Responses + + foreach ($sdk->getResponses() as $response) { + /** @var \Appwrite\SDK\Response $response */ + $model = $response->getModel(); + + foreach ($this->models as $value) { + if (\is_array($model)) { + $model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model); + } else { + if ($value->getType() === $model) { + $model = $value; + break; + } } - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => $modelDescription, + } + + if (!(\is_array($model)) && $model->isNone()) { + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => in_array($produces, [ + 'image/*', + 'image/jpeg', + 'image/gif', + 'image/png', + 'image/webp', + 'image/svg-x', + 'image/x-icon', + 'image/bmp', + ]) ? 'Image' : 'File', 'schema' => [ - 'x-oneOf' => \array_map(function ($m) { - return ['$ref' => '#/definitions/' . $m->getType()]; - }, $model) + 'type' => 'file' ], ]; } else { - // Response definition using one type - $usedModels[] = $model->getType(); - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [ - 'description' => $model->getName(), - 'schema' => [ - '$ref' => '#/definitions/' . $model->getType(), - ], - ]; + if (\is_array($model)) { + $modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model)); + // model has multiple possible responses, we will use oneOf + foreach ($model as $m) { + $usedModels[] = $m->getType(); + } + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => $modelDescription, + 'schema' => [ + 'x-oneOf' => \array_map(function ($m) { + return ['$ref' => '#/definitions/' . $m->getType()]; + }, $model) + ], + ]; + } else { + // Response definition using one type + $usedModels[] = $model->getType(); + $temp['responses'][(string)$response->getCode() ?? '500'] = [ + 'description' => $model->getName(), + 'schema' => [ + '$ref' => '#/definitions/' . $model->getType(), + ], + ]; + } } - } - if (in_array($route->getLabel('sdk.response.code', 500), [204, 301, 302, 308], true)) { - $temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content'; - unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']); + if (in_array($response->getCode() ?? 500, [204, 301, 302, 308], true)) { + $temp['responses'][(string)$response->getCode() ?? '500']['description'] = 'No content'; + unset($temp['responses'][(string)$response->getCode() ?? '500']['schema']); + } } if ((!empty($scope))) { // && 'public' != $scope $securities = ['Project' => []]; - foreach ($route->getLabel('sdk.auth', []) as $security) { - if (array_key_exists($security, $this->keys)) { - $securities[$security] = []; + foreach ($sdk->getAuth() as $security) { + /** @var \Appwrite\SDK\AuthType $security */ + if (array_key_exists($security->value, $this->keys)) { + $securities[$security->value] = []; } } @@ -266,7 +330,7 @@ class Swagger2 extends Format $parameters = \array_merge( $route->getParams(), - $route->getLabel('sdk.parameters', []), + $sdk->getAdditionalParameters() ?? [], ); foreach ($parameters as $name => $param) { // Set params @@ -316,7 +380,7 @@ class Swagger2 extends Format $node['x-example'] = false; break; case 'Appwrite\Utopia\Database\Validator\CustomId': - if ($route->getLabel('sdk.methodType', '') === 'upload') { + if ($sdk->getType() === MethodType::UPLOAD) { $node['x-upload-id'] = true; } $node['type'] = $validator->getType(); @@ -423,7 +487,7 @@ class Swagger2 extends Format //Iterate the blackList. If it matches with the current one, then it is blackListed $allowed = true; foreach ($this->enumBlacklist as $blacklist) { - if ($blacklist['namespace'] == $route->getLabel('sdk.namespace', '') && $blacklist['method'] == $method && $blacklist['parameter'] == $name) { + if ($blacklist['namespace'] == $namespace && $blacklist['method'] == $method && $blacklist['parameter'] == $name) { $allowed = false; break; } @@ -431,8 +495,8 @@ class Swagger2 extends Format if ($allowed && $validator->getType() === 'string') { $node['enum'] = $validator->getList(); - $node['x-enum-name'] = $this->getEnumName($route->getLabel('sdk.namespace', ''), $method, $name); - $node['x-enum-keys'] = $this->getEnumKeys($route->getLabel('sdk.namespace', ''), $method, $name); + $node['x-enum-name'] = $this->getEnumName($namespace, $method, $name); + $node['x-enum-keys'] = $this->getEnumKeys($namespace, $method, $name); } if ($validator->getType() === 'integer') { diff --git a/src/Appwrite/Transformation/Adapter.php b/src/Appwrite/Transformation/Adapter.php new file mode 100644 index 0000000000..b4b5dce8a8 --- /dev/null +++ b/src/Appwrite/Transformation/Adapter.php @@ -0,0 +1,32 @@ +<?php + +namespace Appwrite\Transformation; + +abstract class Adapter +{ + protected mixed $input; + protected mixed $output; + + public function __construct() + { + + } + + public function setInput(mixed $input): self + { + $this->input = $input; + return $this; + } + + public function getOutput(): mixed + { + return $this->output; + } + + /** + * @param array<mixed> $traits + */ + abstract public function isValid(array $traits): bool; + + abstract public function transform(): void; +} diff --git a/src/Appwrite/Transformation/Adapter/Mock.php b/src/Appwrite/Transformation/Adapter/Mock.php new file mode 100644 index 0000000000..13ec1cc88b --- /dev/null +++ b/src/Appwrite/Transformation/Adapter/Mock.php @@ -0,0 +1,26 @@ +<?php + +namespace Appwrite\Transformation\Adapter; + +use Appwrite\Transformation\Adapter; + +class Mock extends Adapter +{ + /** + * @param array<mixed> $traits Mock traits + */ + public function isValid(array $traits): bool + { + if ($traits['mock'] === true) { + return true; + } + + return false; + } + + public function transform(): void + { + $this->output = $this->input; + $this->output = "Mock: " . $this->output; + } +} diff --git a/src/Appwrite/Transformation/Adapter/Preview.php b/src/Appwrite/Transformation/Adapter/Preview.php new file mode 100644 index 0000000000..70af19a188 --- /dev/null +++ b/src/Appwrite/Transformation/Adapter/Preview.php @@ -0,0 +1,209 @@ +<?php + +namespace Appwrite\Transformation\Adapter; + +use Appwrite\Transformation\Adapter; + +class Preview extends Adapter +{ + /** + * @param array<mixed> $traits Proxied response headers + */ + public function isValid(array $traits): bool + { + $contentType = ''; + + foreach ($traits as $key => $value) { + if (\strtolower($key) === 'content-type') { + $contentType = $value; + break; + } + } + + if (\str_contains($contentType, 'text/html')) { + return true; + } + + return false; + } + + public function transform(): void + { + $this->output = $this->input; + + $banner = <<<EOT + <style> + @import url(https://fonts.bunny.net/css?family=fira-code:400|inter:400); + + #appwrite-preview { + min-width: auto; + min-height: auto; + max-width: none; + max-height: none; + width: auto; + height: auto; + padding: 0; + margin: 0; + position: fixed; + right: 16px; + bottom: 16px; + z-index: 1; + border-radius: var(--border-radius-S, 8px); + border: var(--border-width-S, 1px) solid var(--color-border-neutral, #EDEDF0); + background: var(--color-bgColor-neutral-primary, #FFF); + box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.03), 0px 4px 4px 0px rgba(0, 0, 0, 0.04); + padding: var(--space-3, 6px) var(--space-4, 8px); + display: flex; + justify-content: center; + align-items: center; + gap: var(--gap-XXS, 4px); + cursor: pointer; + transition: opacity 0.3s; + } + + #appwrite-preview-close { + position: absolute; + right: 0px; + bottom: 0px; + border-radius: var(--border-radius-S, 8px); + background: linear-gradient(270deg, #FFF 69.64%, rgba(255, 255, 255, 0.00) 114.29%); + height: 100%; + aspect-ratio: 1 / 1; + display: flex; + justify-content: center; + align-items: center; + opacity: 0; + transition: opacity 0.3s; + } + + #appwrite-preview-logo-dark { + display: none; + } + + #appwrite-preview:hover #appwrite-preview-close { + opacity: 1; + } + + #appwrite-preview-text { + padding: 0; + margin: 0; + color: var(--color-fgColor-neutral-secondary, #56565C); + font-family: var(--font-family-sansSerif, Inter), sans-serif; + font-size: var(--font-size-XS, 12px); + font-style: normal; + font-weight: 500; + line-height: 130%; + letter-spacing: -0.12px; + } + + #appwrite-preview-close-text { + opacity: 0; + transition: opacity 0.3s; + position: absolute; + bottom: calc(15px + 4px); + display: flex; + padding: var(--space-1, 2px) var(--space-2, 4px); + color: var(--color-fgColor-neutral-secondary, #56565C); + text-align: center; + font-family: var(--font-family-sansSerif, Inter), sans-serif; + font-size: var(--font-size-XS, 12px); + font-style: normal; + font-weight: 400; + line-height: 130%; + letter-spacing: -0.12px; + border-radius: var(--border-radius-XS, 6px); + background: #EDEDF0; + } + + #appwrite-preview-close:hover #appwrite-preview-close-text { + opacity: 1; + } + + @media (prefers-color-scheme: dark) { + #appwrite-preview { + border: var(--border-width-S, 1px) solid var(--color-border-neutral, #2D2D31); + background: var(--color-bgColor-neutral-primary, #1D1D21); + box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.03), 0px 4px 4px 0px rgba(0, 0, 0, 0.04); + } + + #appwrite-preview-text { + color: var(--color-fgColor-neutral-secondary, #C3C3C6); + font-family: var(--font-family-sansSerif, Inter), sans-serif; + font-size: var(--font-size-XS, 12px); + } + + #appwrite-preview-logo-dark { + display: block; + } + + #appwrite-preview-logo-light { + display: none; + } + + #appwrite-preview-close { + background: linear-gradient(270deg, #1D1D21 69.64%, rgba(29, 29, 33, 0.00) 114.29%); + } + + #appwrite-preview-close-text { + background: #2D2D31; + color: var(--color-fgColor-neutral-secondary, #C3C3C6); + } + } + </style> + + <button id="appwrite-preview"> + <p id="appwrite-preview-text">Preview by</p> + + <div id="appwrite-preview-close"> + <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" clip-rule="evenodd" d="M3.43451 3.43439C3.74693 3.12197 4.25346 3.12197 4.56588 3.43439L8.0002 6.8687L11.4345 3.43439C11.7469 3.12197 12.2535 3.12197 12.5659 3.43439C12.8783 3.74681 12.8783 4.25334 12.5659 4.56576L9.13157 8.00007L12.5659 11.4344C12.8783 11.7468 12.8783 12.2533 12.5659 12.5658C12.2535 12.8782 11.7469 12.8782 11.4345 12.5658L8.0002 9.13144L4.56588 12.5658C4.25346 12.8782 3.74693 12.8782 3.43451 12.5658C3.12209 12.2533 3.12209 11.7468 3.43451 11.4344L6.86882 8.00007L3.43451 4.56576C3.12209 4.25334 3.12209 3.74681 3.43451 3.43439Z" fill="#97979B"/> + </svg> + + <p id="appwrite-preview-close-text">Hide</p> + </div> + + <svg id="appwrite-preview-logo-light" width="65" height="12" viewBox="0 0 65 12" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M18.9862 9.74762C20.0493 9.74762 20.5867 9.191 20.8204 8.81202H20.9255C20.9722 9.21468 21.2526 9.59366 21.8017 9.59366H22.8414V8.40936H22.5727C22.3858 8.40936 22.2924 8.30277 22.2924 8.13697V3.38795H20.9138V4.1459H20.8087C20.54 3.76692 19.9792 3.23399 18.9511 3.23399C17.3156 3.23399 16.1006 4.60777 16.1006 6.4908C16.1006 8.37383 17.3389 9.74762 18.9862 9.74762ZM19.2315 8.39752C18.2619 8.39752 17.5025 7.6751 17.5025 6.50265C17.5025 5.35388 18.2385 4.57224 19.2198 4.57224C20.1544 4.57224 20.9372 5.27098 20.9372 6.50265C20.9372 7.55667 20.2713 8.39752 19.2315 8.39752Z" fill="#2D2D31"/> + <path d="M23.6553 12H25.0339V8.81202H25.139C25.396 9.191 25.9451 9.74762 27.0316 9.74762C28.6672 9.74762 29.8588 8.35015 29.8588 6.4908C29.8588 4.61962 28.5854 3.23399 26.9381 3.23399C25.8867 3.23399 25.3727 3.81429 25.1273 4.13405H25.0222V3.38795H23.6553V12ZM26.7395 8.43305C25.7933 8.43305 25.0105 7.72247 25.0105 6.4908C25.0105 5.43678 25.6764 4.54856 26.7162 4.54856C27.6858 4.54856 28.4452 5.31835 28.4452 6.4908C28.4452 7.63957 27.7092 8.43305 26.7395 8.43305Z" fill="#2D2D31"/> + <path d="M30.5701 12H31.9487V8.81202H32.0538C32.3108 9.191 32.8599 9.74762 33.9464 9.74762C35.582 9.74762 36.66 8.35015 36.66 6.4908C36.66 4.61962 35.5002 3.23399 33.8529 3.23399C32.8015 3.23399 32.2875 3.81429 32.0421 4.13405H31.937V3.38795H30.5701V12ZM33.6543 8.43305C32.708 8.43305 31.9253 7.72247 31.9253 6.4908C31.9253 5.43678 32.5912 4.54856 33.631 4.54856C34.6006 4.54856 35.36 5.31835 35.36 6.4908C35.36 7.63957 34.624 8.43305 33.6543 8.43305Z" fill="#2D2D31"/> + <path d="M38.4823 9.73776H40.4333L41.5431 4.87031H41.6132L42.7231 9.73776H44.6624L46.2153 3.53205H44.8259L43.7161 8.41135H43.6109L42.5011 3.53205H40.6669L39.5454 8.41135H39.4403L38.3421 3.53205H36.8701L38.4823 9.73776Z" fill="#2D2D31"/> + <path d="M46.9137 9.73776H48.2923V6.67044C48.2923 5.49798 48.8297 4.77556 49.8344 4.77556H50.4418V3.37809H49.9862C49.2035 3.37809 48.6077 3.92287 48.374 4.44396H48.2806V3.53205H46.9137V9.73776Z" fill="#2D2D31"/> + <path d="M57.2829 9.73776H58.3577V8.49425H57.2946C56.874 8.49425 56.6988 8.30476 56.6988 7.86657V4.76372H58.4278V3.53205H56.6988V1.79114H55.3903V3.53205H54.2454V4.76372H55.3085V7.87842C55.3085 9.19299 56.0913 9.73776 57.2829 9.73776Z" fill="#2D2D31"/> + <path d="M62.0561 9.74762C63.3295 9.74762 64.451 9.1081 64.8482 7.81721L63.5865 7.5093C63.3645 8.19619 62.722 8.55148 62.0444 8.55148C61.0397 8.55148 60.3738 7.88827 60.3621 6.84609H65.0001V6.45527C65.0001 4.60777 63.8669 3.23399 61.9977 3.23399C60.3504 3.23399 58.9368 4.54856 58.9368 6.50265C58.9368 8.39752 60.1869 9.74762 62.0561 9.74762ZM60.3738 5.8276C60.4556 5.08149 61.1215 4.45381 61.9977 4.45381C62.8388 4.45381 63.5281 4.98675 63.5982 5.8276H60.3738Z" fill="#2D2D31"/> + <path fill-rule="evenodd" clip-rule="evenodd" d="M53.6325 9.73776H52.2539V4.76372H51.1791V3.53205H53.6325V9.73776Z" fill="#2D2D31"/> + <path d="M52.841 2.67085C53.3434 2.67085 53.7172 2.29187 53.7172 1.79447C53.7172 1.30891 53.3434 0.929932 52.841 0.929932C52.3387 0.929932 51.9648 1.30891 51.9648 1.79447C51.9648 2.29187 52.3387 2.67085 52.841 2.67085Z" fill="#2D2D31"/> + <path d="M12.0363 8.21609V10.9548H5.29451C3.33035 10.9548 1.61537 9.85334 0.697814 8.21609C0.564426 7.97807 0.447681 7.72836 0.349751 7.46917C0.157509 6.96127 0.0366636 6.41627 0 5.84762V5.10717C0.00795985 4.98044 0.0205026 4.85471 0.0369048 4.73048C0.0704326 4.47553 0.121086 4.22606 0.18766 3.98356C0.817453 1.68455 2.86531 0 5.29451 0C7.72371 0 9.77132 1.68455 10.4011 3.98356H7.51844C7.04519 3.23415 6.22605 2.7387 5.29451 2.7387C4.36296 2.7387 3.54382 3.23415 3.07057 3.98356C2.92633 4.21137 2.81441 4.46258 2.74108 4.73048C2.67596 4.968 2.64122 5.21846 2.64122 5.47739C2.64122 6.2624 2.96106 6.96999 3.47387 7.46917C3.94905 7.93251 4.5897 8.21609 5.29451 8.21609H12.0363Z" fill="#FD366E"/> + <path d="M12.0364 4.73047V7.46917H7.11523C7.62804 6.96998 7.94788 6.2624 7.94788 5.47739C7.94788 5.21846 7.91315 4.96799 7.84802 4.73047H12.0364Z" fill="#FD366E"/> + </svg> + + <svg id="appwrite-preview-logo-dark" width="65" height="12" viewBox="0 0 65 12" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M18.9862 9.74762C20.0493 9.74762 20.5867 9.191 20.8204 8.81202H20.9255C20.9722 9.21468 21.2526 9.59366 21.8017 9.59366H22.8414V8.40936H22.5727C22.3858 8.40936 22.2924 8.30277 22.2924 8.13697V3.38795H20.9138V4.1459H20.8087C20.54 3.76692 19.9792 3.23399 18.9511 3.23399C17.3156 3.23399 16.1006 4.60777 16.1006 6.4908C16.1006 8.37383 17.3389 9.74762 18.9862 9.74762ZM19.2315 8.39752C18.2619 8.39752 17.5025 7.6751 17.5025 6.50265C17.5025 5.35388 18.2385 4.57224 19.2198 4.57224C20.1544 4.57224 20.9372 5.27098 20.9372 6.50265C20.9372 7.55667 20.2713 8.39752 19.2315 8.39752Z" fill="#EDEDF0"/> + <path d="M23.6553 12H25.0339V8.81202H25.139C25.396 9.191 25.9451 9.74762 27.0316 9.74762C28.6672 9.74762 29.8588 8.35015 29.8588 6.4908C29.8588 4.61962 28.5854 3.23399 26.9381 3.23399C25.8867 3.23399 25.3727 3.81429 25.1273 4.13405H25.0222V3.38795H23.6553V12ZM26.7395 8.43305C25.7933 8.43305 25.0105 7.72247 25.0105 6.4908C25.0105 5.43678 25.6764 4.54856 26.7162 4.54856C27.6858 4.54856 28.4452 5.31835 28.4452 6.4908C28.4452 7.63957 27.7092 8.43305 26.7395 8.43305Z" fill="#EDEDF0"/> + <path d="M30.5701 12H31.9487V8.81202H32.0538C32.3108 9.191 32.8599 9.74762 33.9464 9.74762C35.582 9.74762 36.66 8.35015 36.66 6.4908C36.66 4.61962 35.5002 3.23399 33.8529 3.23399C32.8015 3.23399 32.2875 3.81429 32.0421 4.13405H31.937V3.38795H30.5701V12ZM33.6543 8.43305C32.708 8.43305 31.9253 7.72247 31.9253 6.4908C31.9253 5.43678 32.5912 4.54856 33.631 4.54856C34.6006 4.54856 35.36 5.31835 35.36 6.4908C35.36 7.63957 34.624 8.43305 33.6543 8.43305Z" fill="#EDEDF0"/> + <path d="M38.4823 9.73776H40.4333L41.5431 4.87031H41.6132L42.7231 9.73776H44.6624L46.2153 3.53205H44.8259L43.7161 8.41135H43.6109L42.5011 3.53205H40.6669L39.5454 8.41135H39.4403L38.3421 3.53205H36.8701L38.4823 9.73776Z" fill="#EDEDF0"/> + <path d="M46.9137 9.73776H48.2923V6.67044C48.2923 5.49798 48.8297 4.77556 49.8344 4.77556H50.4418V3.37809H49.9862C49.2035 3.37809 48.6077 3.92287 48.374 4.44396H48.2806V3.53205H46.9137V9.73776Z" fill="#EDEDF0"/> + <path d="M57.2829 9.73776H58.3577V8.49425H57.2946C56.874 8.49425 56.6988 8.30476 56.6988 7.86657V4.76372H58.4278V3.53205H56.6988V1.79114H55.3903V3.53205H54.2454V4.76372H55.3085V7.87842C55.3085 9.19299 56.0913 9.73776 57.2829 9.73776Z" fill="#EDEDF0"/> + <path d="M62.0561 9.74762C63.3295 9.74762 64.451 9.1081 64.8482 7.81721L63.5865 7.5093C63.3645 8.19619 62.722 8.55148 62.0444 8.55148C61.0397 8.55148 60.3738 7.88827 60.3621 6.84609H65.0001V6.45527C65.0001 4.60777 63.8669 3.23399 61.9977 3.23399C60.3504 3.23399 58.9368 4.54856 58.9368 6.50265C58.9368 8.39752 60.1869 9.74762 62.0561 9.74762ZM60.3738 5.8276C60.4556 5.08149 61.1215 4.45381 61.9977 4.45381C62.8388 4.45381 63.5281 4.98675 63.5982 5.8276H60.3738Z" fill="#EDEDF0"/> + <path fill-rule="evenodd" clip-rule="evenodd" d="M53.6325 9.73776H52.2539V4.76372H51.1791V3.53205H53.6325V9.73776Z" fill="#EDEDF0"/> + <path d="M52.841 2.67085C53.3434 2.67085 53.7172 2.29187 53.7172 1.79447C53.7172 1.30891 53.3434 0.929932 52.841 0.929932C52.3387 0.929932 51.9648 1.30891 51.9648 1.79447C51.9648 2.29187 52.3387 2.67085 52.841 2.67085Z" fill="#EDEDF0"/> + <path d="M12.0363 8.21609V10.9548H5.29451C3.33035 10.9548 1.61537 9.85334 0.697814 8.21609C0.564426 7.97807 0.447681 7.72836 0.349751 7.46917C0.157509 6.96127 0.0366636 6.41627 0 5.84762V5.10717C0.00795985 4.98044 0.0205026 4.85471 0.0369048 4.73048C0.0704326 4.47553 0.121086 4.22606 0.18766 3.98356C0.817453 1.68455 2.86531 0 5.29451 0C7.72371 0 9.77132 1.68455 10.4011 3.98356H7.51844C7.04519 3.23415 6.22605 2.7387 5.29451 2.7387C4.36296 2.7387 3.54382 3.23415 3.07057 3.98356C2.92633 4.21137 2.81441 4.46258 2.74108 4.73048C2.67596 4.968 2.64122 5.21846 2.64122 5.47739C2.64122 6.2624 2.96106 6.96999 3.47387 7.46917C3.94905 7.93251 4.5897 8.21609 5.29451 8.21609H12.0363Z" fill="#FD366E"/> + <path d="M12.0364 4.73047V7.46917H7.11523C7.62804 6.96998 7.94788 6.2624 7.94788 5.47739C7.94788 5.21846 7.91315 4.96799 7.84802 4.73047H12.0364Z" fill="#FD366E"/> + </svg> + </button> + + <script> + (function() { + var banner = document.getElementById("appwrite-preview"); + banner.addEventListener("click", function() { + banner.style.opacity = 0; + setTimeout(() => { + banner.style.display = 'none'; + }, 350); + }); + })(); + </script> + EOT; + + $this->output .= $banner; + } +} diff --git a/src/Appwrite/Transformation/Transformation.php b/src/Appwrite/Transformation/Transformation.php new file mode 100644 index 0000000000..d01ee08179 --- /dev/null +++ b/src/Appwrite/Transformation/Transformation.php @@ -0,0 +1,74 @@ +<?php + +namespace Appwrite\Transformation; + +class Transformation +{ + /** + * @var array<Adapter> $adapters + */ + protected array $adapters; + + /** + * @var array<mixed> $traits + */ + protected array $traits; + + protected mixed $input; + protected mixed $output; + + /** + * @param array<Adapter> $adapters + */ + public function __construct(array $adapters = []) + { + $this->adapters = $adapters; + } + + /** + * @param array<mixed> $traits + */ + public function setTraits(array $traits): self + { + $this->traits = $traits; + return $this; + } + + public function setInput(mixed $input): self + { + $this->input = $input; + return $this; + } + + public function addAdapter(Adapter $adapter): self + { + $this->adapters[] = $adapter; + return $this; + } + + public function transform(): bool + { + foreach ($this->adapters as $adapter) { + if (!$adapter->isValid($this->traits)) { + return false; + } + } + + $output = $this->input; + + foreach ($this->adapters as $adapter) { + $adapter->setInput($output); + $adapter->transform(); + $output = $adapter->getOutput(); + } + + $this->output = $output; + + return true; + } + + public function getOutput(): mixed + { + return $this->output; + } +} diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index af5d59ddfd..e8eafba5a0 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -24,7 +24,15 @@ class Base extends Queries public function __construct(string $collection, array $allowedAttributes) { $config = Config::getParam('collections', []); - $collections = array_merge($config['projects'], $config['buckets'], $config['databases'], $config['console']); + + $collections = array_merge( + $config['projects'], + $config['buckets'], + $config['databases'], + $config['console'], + $config['logs'] + ); + $collection = $collections[$collection]; // array for constant lookup time $allowedAttributesLookup = []; @@ -35,6 +43,7 @@ class Base extends Queries $attributes = []; foreach ($collection['attributes'] as $attribute) { $key = $attribute['$id']; + if (!isset($allowedAttributesLookup[$key])) { continue; } @@ -62,12 +71,18 @@ class Base extends Queries 'array' => false, ]); + $internalId = new Document([ + 'key' => '$internalId', + 'type' => Database::VAR_STRING, + 'array' => false, + ]); + $validators = [ new Limit(), new Offset(), new Cursor(), new Filter($attributes, APP_DATABASE_QUERY_MAX_VALUES), - new Order($attributes), + new Order([...$attributes, $internalId]), ]; parent::__construct($validators); diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php index 42aed88ef6..73631ecfb8 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Deployments.php @@ -5,13 +5,13 @@ namespace Appwrite\Utopia\Database\Validator\Queries; class Deployments extends Base { public const ALLOWED_ATTRIBUTES = [ - 'size', - 'buildId', + 'buildSize', + 'sourceSize', + 'totalSize', + 'buildDuration', + 'status', 'activate', - 'entrypoint', - 'commands', 'type', - 'size' ]; /** diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php index 89f5d52c81..894ee26e3f 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Functions.php @@ -8,7 +8,7 @@ class Functions extends Base 'name', 'enabled', 'runtime', - 'deployment', + 'deploymentId', 'schedule', 'scheduleNext', 'schedulePrevious', diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Logs.php b/src/Appwrite/Utopia/Database/Validator/Queries/Logs.php new file mode 100644 index 0000000000..d07d3dd3d2 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Logs.php @@ -0,0 +1,24 @@ +<?php + +namespace Appwrite\Utopia\Database\Validator\Queries; + +class Logs extends Base +{ + public const ALLOWED_ATTRIBUTES = [ + 'status', + 'responseStatusCode', + 'duration', + 'requestMethod', + 'requestPath', + 'deploymentId' + ]; + + /** + * Expression constructor + * + */ + public function __construct() + { + parent::__construct('executions', self::ALLOWED_ATTRIBUTES); //TODO: Update this later + } +} diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php b/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php index 5ff0098662..cef562ba2c 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Memberships.php @@ -9,12 +9,12 @@ class Memberships extends Base 'teamId', 'invited', 'joined', - 'confirm' + 'confirm', + 'roles', ]; /** * Expression constructor - * */ public function __construct() { diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Rules.php b/src/Appwrite/Utopia/Database/Validator/Queries/Rules.php index 24cb4475f2..c8057162a8 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Rules.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Rules.php @@ -6,9 +6,12 @@ class Rules extends Base { public const ALLOWED_ATTRIBUTES = [ 'domain', - 'resourceType', - 'resourceId', - 'url' + 'type', + 'trigger', + 'deploymentResourceType', + 'deploymentResourceId', + 'deploymentId', + 'deploymentVcsProviderBranch' ]; /** diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Sites.php b/src/Appwrite/Utopia/Database/Validator/Queries/Sites.php new file mode 100644 index 0000000000..35d4bdb5ef --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Sites.php @@ -0,0 +1,26 @@ +<?php + +namespace Appwrite\Utopia\Database\Validator\Queries; + +class Sites extends Base +{ + public const ALLOWED_ATTRIBUTES = [ + 'name', + 'enabled', + 'framework', + 'deploymentId', + 'buildCommand', + 'installCommand', + 'outputDirectory', + 'installationId' + ]; + + /** + * Expression constructor + * + */ + public function __construct() + { + parent::__construct('sites', self::ALLOWED_ATTRIBUTES); + } +} diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index 26c1baf188..01f0574357 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -2,8 +2,10 @@ namespace Appwrite\Utopia; +use Appwrite\Auth\Auth; use Appwrite\Utopia\Request\Filter; use Swoole\Http\Request as SwooleRequest; +use Utopia\Database\Validator\Authorization; use Utopia\Route; use Utopia\Swoole\Request as UtopiaRequest; @@ -28,8 +30,30 @@ class Request extends UtopiaRequest $parameters = parent::getParams(); if ($this->hasFilters() && self::hasRoute()) { - $method = self::getRoute()->getLabel('sdk.method', 'unknown'); - $endpointIdentifier = self::getRoute()->getLabel('sdk.namespace', 'unknown') . '.' . $method; + $methods = self::getRoute()->getLabel('sdk', null); + + if (!\is_array($methods)) { + $methods = [$methods]; + } + + $methods = \array_filter($methods, function ($method) { + return !empty($method); + }); + + $params = []; + $endpointIdentifier = 'unknown.unknown'; + + foreach ($methods as $method) { + /** @var \Appwrite\SDK\Method $method */ + $endpointIdentifier = $method->getNamespace() . '.' . $method->getMethodName(); + $params += $method->getParameters(); + } + + if (!empty($params)) { + $parameters = array_filter($parameters, function ($key) use ($params) { + return array_key_exists($key, $params); + }, \ARRAY_FILTER_USE_KEY); + } foreach ($this->getFilters() as $filter) { $parameters = $filter->parse($parameters, $endpointIdentifier); @@ -158,4 +182,27 @@ class Request extends UtopiaRequest $headers = $this->getHeaders(); return $headers[$key] ?? $default; } + + /** + * Get User Agent + * + * Method for getting User Agent. Preferring forwarded agent for privileged users; otherwise returns default. + * + * @param string $default + * @return string + */ + public function getUserAgent(string $default = ''): string + { + $forwardedUserAgent = $this->getHeader('x-forwarded-user-agent'); + if (!empty($forwardedUserAgent)) { + $roles = Authorization::getRoles(); + $isAppUser = Auth::isAppUser($roles); + + if ($isAppUser) { + return $forwardedUserAgent; + } + } + + return UtopiaRequest::getUserAgent($default); + } } diff --git a/src/Appwrite/Utopia/Request/Filters/V19.php b/src/Appwrite/Utopia/Request/Filters/V19.php new file mode 100644 index 0000000000..041c126a69 --- /dev/null +++ b/src/Appwrite/Utopia/Request/Filters/V19.php @@ -0,0 +1,24 @@ +<?php + +namespace Appwrite\Utopia\Request\Filters; + +use Appwrite\Utopia\Request\Filter; + +class V19 extends Filter +{ + // Convert 1.6 params to 1.7 + public function parse(array $content, string $model): array + { + /* + Uncomment with first request filter; current is just a copy of V18 + switch ($model) { + case 'functions.create': + $content['something'] = $content['somethingElse'] ?? ""; + unset($content['something']); + break; + } + */ + + return $content; + } +} diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 6cc2639f51..472c957271 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -30,7 +30,6 @@ use Appwrite\Utopia\Response\Model\AuthProvider; use Appwrite\Utopia\Response\Model\BaseList; use Appwrite\Utopia\Response\Model\Branch; use Appwrite\Utopia\Response\Model\Bucket; -use Appwrite\Utopia\Response\Model\Build; use Appwrite\Utopia\Response\Model\Collection; use Appwrite\Utopia\Response\Model\ConsoleVariables; use Appwrite\Utopia\Response\Model\Continent; @@ -38,12 +37,15 @@ use Appwrite\Utopia\Response\Model\Country; use Appwrite\Utopia\Response\Model\Currency; use Appwrite\Utopia\Response\Model\Database; use Appwrite\Utopia\Response\Model\Deployment; -use Appwrite\Utopia\Response\Model\Detection; +use Appwrite\Utopia\Response\Model\DetectionFramework; +use Appwrite\Utopia\Response\Model\DetectionRuntime; use Appwrite\Utopia\Response\Model\Document as ModelDocument; use Appwrite\Utopia\Response\Model\Error; use Appwrite\Utopia\Response\Model\ErrorDev; use Appwrite\Utopia\Response\Model\Execution; use Appwrite\Utopia\Response\Model\File; +use Appwrite\Utopia\Response\Model\Framework; +use Appwrite\Utopia\Response\Model\FrameworkAdapter; use Appwrite\Utopia\Response\Model\Func; use Appwrite\Utopia\Response\Model\Headers; use Appwrite\Utopia\Response\Model\HealthAntivirus; @@ -81,16 +83,21 @@ use Appwrite\Utopia\Response\Model\Preferences; use Appwrite\Utopia\Response\Model\Project; use Appwrite\Utopia\Response\Model\Provider; use Appwrite\Utopia\Response\Model\ProviderRepository; +use Appwrite\Utopia\Response\Model\ProviderRepositoryFramework; +use Appwrite\Utopia\Response\Model\ProviderRepositoryRuntime; use Appwrite\Utopia\Response\Model\Rule; use Appwrite\Utopia\Response\Model\Runtime; use Appwrite\Utopia\Response\Model\Session; +use Appwrite\Utopia\Response\Model\Site; use Appwrite\Utopia\Response\Model\Specification; use Appwrite\Utopia\Response\Model\Subscriber; use Appwrite\Utopia\Response\Model\Target; use Appwrite\Utopia\Response\Model\Team; use Appwrite\Utopia\Response\Model\TemplateEmail; +use Appwrite\Utopia\Response\Model\TemplateFramework; use Appwrite\Utopia\Response\Model\TemplateFunction; use Appwrite\Utopia\Response\Model\TemplateRuntime; +use Appwrite\Utopia\Response\Model\TemplateSite; use Appwrite\Utopia\Response\Model\TemplateSMS; use Appwrite\Utopia\Response\Model\TemplateVariable; use Appwrite\Utopia\Response\Model\Token; @@ -102,6 +109,8 @@ use Appwrite\Utopia\Response\Model\UsageDatabases; use Appwrite\Utopia\Response\Model\UsageFunction; use Appwrite\Utopia\Response\Model\UsageFunctions; use Appwrite\Utopia\Response\Model\UsageProject; +use Appwrite\Utopia\Response\Model\UsageSite; +use Appwrite\Utopia\Response\Model\UsageSites; use Appwrite\Utopia\Response\Model\UsageStorage; use Appwrite\Utopia\Response\Model\UsageUsers; use Appwrite\Utopia\Response\Model\User; @@ -140,6 +149,8 @@ class Response extends SwooleResponse public const MODEL_USAGE_STORAGE = 'usageStorage'; public const MODEL_USAGE_FUNCTIONS = 'usageFunctions'; public const MODEL_USAGE_FUNCTION = 'usageFunction'; + public const MODEL_USAGE_SITES = 'usageSites'; + public const MODEL_USAGE_SITE = 'usageSite'; public const MODEL_USAGE_PROJECT = 'usageProject'; // Database @@ -238,12 +249,27 @@ class Response extends SwooleResponse public const MODEL_INSTALLATION_LIST = 'installationList'; public const MODEL_PROVIDER_REPOSITORY = 'providerRepository'; public const MODEL_PROVIDER_REPOSITORY_LIST = 'providerRepositoryList'; + public const MODEL_PROVIDER_REPOSITORY_FRAMEWORK = 'providerRepositoryFramework'; + public const MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST = 'providerRepositoryFrameworkList'; + public const MODEL_PROVIDER_REPOSITORY_RUNTIME = 'providerRepositoryRuntime'; + public const MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST = 'providerRepositoryRuntimeList'; public const MODEL_BRANCH = 'branch'; public const MODEL_BRANCH_LIST = 'branchList'; - public const MODEL_DETECTION = 'detection'; + public const MODEL_DETECTION_FRAMEWORK = 'detectionFramework'; + public const MODEL_DETECTION_RUNTIME = 'detectionRuntime'; public const MODEL_VCS_CONTENT = 'vcsContent'; public const MODEL_VCS_CONTENT_LIST = 'vcsContentList'; + // Sites + public const MODEL_SITE = 'site'; + public const MODEL_SITE_LIST = 'siteList'; + public const MODEL_FRAMEWORK = 'framework'; + public const MODEL_FRAMEWORK_LIST = 'frameworkList'; + public const MODEL_FRAMEWORK_ADAPTER = 'frameworkAdapter'; + public const MODEL_TEMPLATE_SITE = 'templateSite'; + public const MODEL_TEMPLATE_SITE_LIST = 'templateSiteList'; + public const MODEL_TEMPLATE_FRAMEWORK = 'templateFramework'; + // Functions public const MODEL_FUNCTION = 'function'; public const MODEL_FUNCTION_LIST = 'functionList'; @@ -253,8 +279,6 @@ class Response extends SwooleResponse public const MODEL_DEPLOYMENT_LIST = 'deploymentList'; public const MODEL_EXECUTION = 'execution'; public const MODEL_EXECUTION_LIST = 'executionList'; - public const MODEL_BUILD = 'build'; - public const MODEL_BUILD_LIST = 'buildList'; // Not used anywhere yet public const MODEL_FUNC_PERMISSIONS = 'funcPermissions'; public const MODEL_HEADERS = 'headers'; public const MODEL_SPECIFICATION = 'specification'; @@ -351,15 +375,18 @@ class Response extends SwooleResponse ->setModel(new BaseList('Buckets List', self::MODEL_BUCKET_LIST, 'buckets', self::MODEL_BUCKET)) ->setModel(new BaseList('Teams List', self::MODEL_TEAM_LIST, 'teams', self::MODEL_TEAM)) ->setModel(new BaseList('Memberships List', self::MODEL_MEMBERSHIP_LIST, 'memberships', self::MODEL_MEMBERSHIP)) + ->setModel(new BaseList('Sites List', self::MODEL_SITE_LIST, 'sites', self::MODEL_SITE)) + ->setModel(new BaseList('Site Templates List', self::MODEL_TEMPLATE_SITE_LIST, 'templates', self::MODEL_TEMPLATE_SITE)) ->setModel(new BaseList('Functions List', self::MODEL_FUNCTION_LIST, 'functions', self::MODEL_FUNCTION)) ->setModel(new BaseList('Function Templates List', self::MODEL_TEMPLATE_FUNCTION_LIST, 'templates', self::MODEL_TEMPLATE_FUNCTION)) ->setModel(new BaseList('Installations List', self::MODEL_INSTALLATION_LIST, 'installations', self::MODEL_INSTALLATION)) - ->setModel(new BaseList('Provider Repositories List', self::MODEL_PROVIDER_REPOSITORY_LIST, 'providerRepositories', self::MODEL_PROVIDER_REPOSITORY)) + ->setModel(new BaseList('Framework Provider Repositories List', self::MODEL_PROVIDER_REPOSITORY_FRAMEWORK_LIST, 'frameworkProviderRepositories', self::MODEL_PROVIDER_REPOSITORY_FRAMEWORK)) + ->setModel(new BaseList('Runtime Provider Repositories List', self::MODEL_PROVIDER_REPOSITORY_RUNTIME_LIST, 'runtimeProviderRepositories', self::MODEL_PROVIDER_REPOSITORY_RUNTIME)) ->setModel(new BaseList('Branches List', self::MODEL_BRANCH_LIST, 'branches', self::MODEL_BRANCH)) + ->setModel(new BaseList('Frameworks List', self::MODEL_FRAMEWORK_LIST, 'frameworks', self::MODEL_FRAMEWORK)) ->setModel(new BaseList('Runtimes List', self::MODEL_RUNTIME_LIST, 'runtimes', self::MODEL_RUNTIME)) ->setModel(new BaseList('Deployments List', self::MODEL_DEPLOYMENT_LIST, 'deployments', self::MODEL_DEPLOYMENT)) ->setModel(new BaseList('Executions List', self::MODEL_EXECUTION_LIST, 'executions', self::MODEL_EXECUTION)) - ->setModel(new BaseList('Builds List', self::MODEL_BUILD_LIST, 'builds', self::MODEL_BUILD)) // Not used anywhere yet ->setModel(new BaseList('Projects List', self::MODEL_PROJECT_LIST, 'projects', self::MODEL_PROJECT, true, false)) ->setModel(new BaseList('Webhooks List', self::MODEL_WEBHOOK_LIST, 'webhooks', self::MODEL_WEBHOOK, true, false)) ->setModel(new BaseList('API Keys List', self::MODEL_KEY_LIST, 'keys', self::MODEL_KEY, true, false)) @@ -422,19 +449,26 @@ class Response extends SwooleResponse ->setModel(new Bucket()) ->setModel(new Team()) ->setModel(new Membership()) + ->setModel(new Site()) + ->setModel(new TemplateSite()) + ->setModel(new TemplateFramework()) ->setModel(new Func()) ->setModel(new TemplateFunction()) ->setModel(new TemplateRuntime()) ->setModel(new TemplateVariable()) ->setModel(new Installation()) ->setModel(new ProviderRepository()) - ->setModel(new Detection()) + ->setModel(new ProviderRepositoryFramework()) + ->setModel(new ProviderRepositoryRuntime()) + ->setModel(new DetectionFramework()) + ->setModel(new DetectionRuntime()) ->setModel(new VcsContent()) ->setModel(new Branch()) ->setModel(new Runtime()) + ->setModel(new Framework()) + ->setModel(new FrameworkAdapter()) ->setModel(new Deployment()) ->setModel(new Execution()) - ->setModel(new Build()) ->setModel(new Project()) ->setModel(new Webhook()) ->setModel(new Key()) @@ -463,6 +497,8 @@ class Response extends SwooleResponse ->setModel(new UsageBuckets()) ->setModel(new UsageFunctions()) ->setModel(new UsageFunction()) + ->setModel(new UsageSites()) + ->setModel(new UsageSite()) ->setModel(new UsageProject()) ->setModel(new Headers()) ->setModel(new Specification()) diff --git a/src/Appwrite/Utopia/Response/Filters/V19.php b/src/Appwrite/Utopia/Response/Filters/V19.php new file mode 100644 index 0000000000..2987c5a7e4 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Filters/V19.php @@ -0,0 +1,30 @@ +<?php + +namespace Appwrite\Utopia\Response\Filters; + +use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Filter; + +class V19 extends Filter +{ + // Convert 1.7 Data format to 1.6 format + public function parse(array $content, string $model): array + { + $parsedResponse = $content; + + $parsedResponse = match($model) { + Response::MODEL_FUNCTION => $this->parseFunction($content), + Response::MODEL_FUNCTION_LIST => $this->handleList($content, 'functions', fn ($item) => $this->parseFunction($item)), + default => $parsedResponse, + }; + + return $parsedResponse; + } + + protected function parseFunction(array $content) + { + $content['deployment'] = $content['deploymentId'] ?? ''; + unset($content['deploymentId']); + return $content; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/Build.php b/src/Appwrite/Utopia/Response/Model/Build.php deleted file mode 100644 index d80c17645a..0000000000 --- a/src/Appwrite/Utopia/Response/Model/Build.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php - -namespace Appwrite\Utopia\Response\Model; - -use Appwrite\Utopia\Response; -use Appwrite\Utopia\Response\Model; - -class Build extends Model -{ - public function __construct() - { - $this - ->addRule('$id', [ - 'type' => self::TYPE_STRING, - 'description' => 'Build ID.', - 'default' => '', - 'example' => '5e5ea5c16897e', - ]) - ->addRule('deploymentId', [ - 'type' => self::TYPE_STRING, - 'description' => 'The deployment that created this build.', - 'default' => '', - 'example' => '5e5ea5c16897e', - ]) - // Build Status - // Failed - The deployment build has failed. More details can usually be found in buildStderr - // Ready - The deployment build was successful and the deployment is ready to be deployed - // Processing - The deployment is currently waiting to have a build triggered - // Building - The deployment is currently being built - ->addRule('status', [ - 'type' => self::TYPE_STRING, - 'description' => 'The build status. There are a few different types and each one means something different. \nFailed - The deployment build has failed. More details can usually be found in buildStderr\nReady - The deployment build was successful and the deployment is ready to be deployed\nProcessing - The deployment is currently waiting to have a build triggered\nBuilding - The deployment is currently being built', - 'default' => '', - 'example' => 'ready', - ]) - ->addRule('stdout', [ - 'type' => self::TYPE_STRING, - 'description' => 'The stdout of the build.', - 'default' => '', - 'example' => '', - ]) - ->addRule('stderr', [ - 'type' => self::TYPE_STRING, - 'description' => 'The stderr of the build.', - 'default' => '', - 'example' => '', - ]) - ->addRule('startTime', [ - 'type' => self::TYPE_DATETIME, - 'description' => 'The deployment creation date in ISO 8601 format.', - 'default' => '', - 'example' => self::TYPE_DATETIME_EXAMPLE, - ]) - ->addRule('endTime', [ - 'type' => self::TYPE_DATETIME, - 'description' => 'The time the build was finished in ISO 8601 format.', - 'default' => '', - 'example' => self::TYPE_DATETIME_EXAMPLE, - ]) - ->addRule('duration', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'The build duration in seconds.', - 'default' => 0, - 'example' => 0, - ]) - ->addRule('size', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'The code size in bytes.', - 'default' => 0, - 'example' => 128, - ]) - ; - } - - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'Build'; - } - - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_BUILD; - } -} diff --git a/src/Appwrite/Utopia/Response/Model/ConsoleVariables.php b/src/Appwrite/Utopia/Response/Model/ConsoleVariables.php index a82b8008cc..97dae2efcd 100644 --- a/src/Appwrite/Utopia/Response/Model/ConsoleVariables.php +++ b/src/Appwrite/Utopia/Response/Model/ConsoleVariables.php @@ -10,19 +10,31 @@ class ConsoleVariables extends Model public function __construct() { $this - ->addRule('_APP_DOMAIN_TARGET', [ - 'type' => self::TYPE_STRING, - 'description' => 'CNAME target for your Appwrite custom domains.', - 'default' => '', - 'example' => 'appwrite.io', - ]) + ->addRule('_APP_DOMAIN_TARGET_CNAME', [ + 'type' => self::TYPE_STRING, + 'description' => 'CNAME target for your Appwrite custom domains.', + 'default' => '', + 'example' => 'appwrite.io', + ]) + ->addRule('_APP_DOMAIN_TARGET_A', [ + 'type' => self::TYPE_STRING, + 'description' => 'A target for your Appwrite custom domains.', + 'default' => '', + 'example' => '127.0.0.1', + ]) + ->addRule('_APP_DOMAIN_TARGET_AAAA', [ + 'type' => self::TYPE_STRING, + 'description' => 'AAAA target for your Appwrite custom domains.', + 'default' => '', + 'example' => '::1', + ]) ->addRule('_APP_STORAGE_LIMIT', [ 'type' => self::TYPE_INTEGER, 'description' => 'Maximum file size allowed for file upload in bytes.', 'default' => '', 'example' => '30000000', ]) - ->addRule('_APP_FUNCTIONS_SIZE_LIMIT', [ + ->addRule('_APP_COMPUTE_SIZE_LIMIT', [ 'type' => self::TYPE_INTEGER, 'description' => 'Maximum file size allowed for deployment in bytes.', 'default' => '', @@ -51,7 +63,37 @@ class ConsoleVariables extends Model 'description' => 'Defines if AI assistant is enabled.', 'default' => false, 'example' => true, - ]); + ]) + ->addRule('_APP_DOMAIN_SITES', [ + 'type' => self::TYPE_STRING, + 'description' => 'A domain to use for site URLs.', + 'default' => '', + 'example' => 'sites.localhost', + ]) + ->addRule('_APP_DOMAIN_FUNCTIONS', [ + 'type' => self::TYPE_STRING, + 'description' => 'A domain to use for function URLs.', + 'default' => '', + 'example' => 'functions.localhost', + ]) + ->addRule( + '_APP_OPTIONS_FORCE_HTTPS', + [ + 'type' => self::TYPE_STRING, + 'description' => 'Defines if HTTPS is enforced for all requests.', + 'default' => '', + 'example' => 'enabled', + ] + ) + ->addRule( + '_APP_DOMAINS_NAMESERVERS', + [ + 'type' => self::TYPE_STRING, + 'description' => 'Comma-separated list of nameservers.', + 'default' => '', + 'example' => 'ns1.example.com,ns2.example.com', + ] + ); } /** diff --git a/src/Appwrite/Utopia/Response/Model/Deployment.php b/src/Appwrite/Utopia/Response/Model/Deployment.php index 91a9f40956..55c1589af0 100644 --- a/src/Appwrite/Utopia/Response/Model/Deployment.php +++ b/src/Appwrite/Utopia/Response/Model/Deployment.php @@ -52,7 +52,7 @@ class Deployment extends Model 'default' => '', 'example' => 'index.js', ]) - ->addRule('size', [ + ->addRule('sourceSize', [ 'type' => self::TYPE_INTEGER, 'description' => 'The code size in bytes.', 'default' => 0, @@ -64,6 +64,12 @@ class Deployment extends Model 'default' => 0, 'example' => 128, ]) + ->addRule('totalSize', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'The total size in bytes (source and build output).', + 'default' => 0, + 'example' => 128, + ]) ->addRule('buildId', [ 'type' => self::TYPE_STRING, 'description' => 'The current build ID.', @@ -76,9 +82,21 @@ class Deployment extends Model 'default' => false, 'example' => true, ]) + ->addRule('screenshotLight', [ + 'type' => self::TYPE_STRING, + 'description' => 'Screenshot with light theme preference file ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('screenshotDark', [ + 'type' => self::TYPE_STRING, + 'description' => 'Screenshot with dark theme preference file ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) ->addRule('status', [ 'type' => self::TYPE_STRING, - 'description' => 'The deployment status. Possible values are "processing", "building", "waiting", "ready", and "failed".', + 'description' => 'The deployment status. Possible values are "waiting", "processing", "building", "ready", and "failed".', 'default' => '', 'example' => 'ready', ]) @@ -88,7 +106,7 @@ class Deployment extends Model 'default' => '', 'example' => 'Compiling source files...', ]) - ->addRule('buildTime', [ + ->addRule('buildDuration', [ 'type' => self::TYPE_INTEGER, 'description' => 'The current build time in seconds.', 'default' => 0, diff --git a/src/Appwrite/Utopia/Response/Model/DetectionFramework.php b/src/Appwrite/Utopia/Response/Model/DetectionFramework.php new file mode 100644 index 0000000000..9aeb885f76 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/DetectionFramework.php @@ -0,0 +1,58 @@ +<?php + +namespace Appwrite\Utopia\Response\Model; + +use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Model; + +class DetectionFramework extends Model +{ + public function __construct() + { + $this + ->addRule('framework', [ + 'type' => self::TYPE_STRING, + 'description' => 'Framework', + 'default' => '', + 'example' => 'nuxt', + ]) + ->addRule('installCommand', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site Install Command', + 'default' => '', + 'example' => 'npm install', + ]) + ->addRule('buildCommand', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site Build Command', + 'default' => '', + 'example' => 'npm run build', + ]) + ->addRule('outputDirectory', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site Output Directory', + 'default' => '', + 'example' => 'dist', + ]); + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'DetectionFramework'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_DETECTION_FRAMEWORK; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/Detection.php b/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php similarity index 50% rename from src/Appwrite/Utopia/Response/Model/Detection.php rename to src/Appwrite/Utopia/Response/Model/DetectionRuntime.php index c71baa0b0c..1c7c0be16b 100644 --- a/src/Appwrite/Utopia/Response/Model/Detection.php +++ b/src/Appwrite/Utopia/Response/Model/DetectionRuntime.php @@ -5,7 +5,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -class Detection extends Model +class DetectionRuntime extends Model { public function __construct() { @@ -15,6 +15,18 @@ class Detection extends Model 'description' => 'Runtime', 'default' => '', 'example' => 'node', + ]) + ->addRule('entrypoint', [ + 'type' => self::TYPE_STRING, + 'description' => 'Function Entrypoint', + 'default' => '', + 'example' => 'index.js', + ]) + ->addRule('commands', [ + 'type' => self::TYPE_STRING, + 'description' => 'Function install and build commands', + 'default' => '', + 'example' => 'npm install && npm run build', ]); } @@ -25,7 +37,7 @@ class Detection extends Model */ public function getName(): string { - return 'Detection'; + return 'DetectionRuntime'; } /** @@ -35,6 +47,6 @@ class Detection extends Model */ public function getType(): string { - return Response::MODEL_DETECTION; + return Response::MODEL_DETECTION_RUNTIME; } } diff --git a/src/Appwrite/Utopia/Response/Model/Execution.php b/src/Appwrite/Utopia/Response/Model/Execution.php index 80b65af696..12790ec200 100644 --- a/src/Appwrite/Utopia/Response/Model/Execution.php +++ b/src/Appwrite/Utopia/Response/Model/Execution.php @@ -5,6 +5,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; use Utopia\Database\DateTime; +use Utopia\Database\Document; use Utopia\Database\Helpers\Role; class Execution extends Model @@ -106,7 +107,7 @@ class Execution extends Model ]) ->addRule('duration', [ 'type' => self::TYPE_FLOAT, - 'description' => 'Function execution duration in seconds.', + 'description' => 'Resource(function/site) execution duration in seconds.', 'default' => 0, 'example' => 0.400, ]) @@ -139,4 +140,18 @@ class Execution extends Model { return Response::MODEL_EXECUTION; } + + + /** + * Convert DB structure to response model + * + * @return Document + */ + public function filter(Document $document): Document + { + $document->removeAttribute('resourceType'); + $document->setAttribute('functionId', $document->getAttribute('resourceId', '')); + $document->removeAttribute('resourceId'); + return $document; + } } diff --git a/src/Appwrite/Utopia/Response/Model/Framework.php b/src/Appwrite/Utopia/Response/Model/Framework.php new file mode 100644 index 0000000000..14d4052133 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/Framework.php @@ -0,0 +1,67 @@ +<?php + +namespace Appwrite\Utopia\Response\Model; + +use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Model; + +class Framework extends Model +{ + public function __construct() + { + $this + ->addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Framework key.', + 'default' => '', + 'example' => 'sveltekit', + ]) + ->addRule('name', [ + 'type' => self::TYPE_STRING, + 'description' => 'Framework Name.', + 'default' => '', + 'example' => 'SvelteKit' + ]) + ->addRule('buildRuntime', [ + 'type' => self::TYPE_STRING, + 'description' => 'Default runtime version.', + 'default' => '', + 'example' => 'node-22', + ]) + ->addRule('runtimes', [ + 'type' => self::TYPE_STRING, + 'description' => 'List of supported runtime versions.', + 'default' => '', + 'example' => ['static-1', 'node-22'], + 'array' => true, + ]) + ->addRule('adapters', [ + 'type' => Response::MODEL_FRAMEWORK_ADAPTER, + 'description' => 'List of supported adapters.', + 'default' => '', + 'example' => [[ 'key' => 'static', 'buildRuntime' => 'node-22', 'buildCommand' => 'npm run build', 'installCommand' => 'npm install', 'outputDirectory' => './dist' ]], + 'array' => true, + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'Framework'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_FRAMEWORK; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/FrameworkAdapter.php b/src/Appwrite/Utopia/Response/Model/FrameworkAdapter.php new file mode 100644 index 0000000000..afbd78eda4 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/FrameworkAdapter.php @@ -0,0 +1,65 @@ +<?php + +namespace Appwrite\Utopia\Response\Model; + +use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Model; + +class FrameworkAdapter extends Model +{ + public function __construct() + { + $this + ->addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Adapter key.', + 'default' => '', + 'example' => 'static', + ]) + ->addRule('installCommand', [ + 'type' => self::TYPE_STRING, + 'description' => 'Default command to download dependencies.', + 'default' => '', + 'example' => 'npm install', + ]) + ->addRule('buildCommand', [ + 'type' => self::TYPE_STRING, + 'description' => 'Default command to build site into output directory.', + 'default' => '', + 'example' => 'npm run build', + ]) + ->addRule('outputDirectory', [ + 'type' => self::TYPE_STRING, + 'description' => 'Default output directory of build.', + 'default' => '', + 'example' => './dist', + ]) + ->addRule('fallbackFile', [ + 'type' => self::TYPE_STRING, + 'description' => 'Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.', + 'default' => null, + 'example' => 'index.html', + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'Framework Adapter'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_FRAMEWORK_ADAPTER; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/Func.php b/src/Appwrite/Utopia/Response/Model/Func.php index f4ff214d0b..e33d7663fd 100644 --- a/src/Appwrite/Utopia/Response/Model/Func.php +++ b/src/Appwrite/Utopia/Response/Model/Func.php @@ -55,22 +55,46 @@ class Func extends Model ]) ->addRule('logging', [ 'type' => self::TYPE_BOOLEAN, - 'description' => 'Whether executions will be logged. When set to false, executions will not be logged, but will reduce resource used by your Appwrite project.', + 'description' => 'When disabled, executions will exclude logs and errors, and will be slightly faster.', 'default' => true, 'example' => false, ]) ->addRule('runtime', [ 'type' => self::TYPE_STRING, - 'description' => 'Function execution runtime.', + 'description' => 'Function execution and build runtime.', 'default' => '', 'example' => 'python-3.8', ]) - ->addRule('deployment', [ + ->addRule('deploymentId', [ 'type' => self::TYPE_STRING, 'description' => 'Function\'s active deployment ID.', 'default' => '', 'example' => '5e5ea5c16897e', ]) + ->addRule('deploymentCreatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Active deployment creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('latestDeploymentId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Function\'s latest deployment ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('latestDeploymentCreatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Latest deployment creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('latestDeploymentStatus', [ + 'type' => self::TYPE_STRING, + 'description' => 'Status of latest deployment. Possible values are "waiting", "processing", "building", "ready", and "failed".', + 'default' => '', + 'example' => 'ready', + ]) ->addRule('scopes', [ 'type' => self::TYPE_STRING, 'description' => 'Allowed permission scopes.', @@ -94,7 +118,7 @@ class Func extends Model ]) ->addRule('schedule', [ 'type' => self::TYPE_STRING, - 'description' => 'Function execution schedult in CRON format.', + 'description' => 'Function execution schedule in CRON format.', 'default' => '', 'example' => '5 4 * * *', ]) @@ -119,7 +143,7 @@ class Func extends Model ->addRule('version', [ 'type' => self::TYPE_STRING, 'description' => 'Version of Open Runtimes used for the function.', - 'default' => 'v4', + 'default' => 'v5', 'example' => 'v2', ]) ->addRule('installationId', [ @@ -155,8 +179,8 @@ class Func extends Model ->addRule('specification', [ 'type' => self::TYPE_STRING, 'description' => 'Machine specification for builds and executions.', - 'default' => APP_FUNCTION_SPECIFICATION_DEFAULT, - 'example' => APP_FUNCTION_SPECIFICATION_DEFAULT, + 'default' => APP_COMPUTE_SPECIFICATION_DEFAULT, + 'example' => APP_COMPUTE_SPECIFICATION_DEFAULT, ]) ; } diff --git a/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php b/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php index 29d5621532..ba46afcb77 100644 --- a/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php +++ b/src/Appwrite/Utopia/Response/Model/MetricBreakdown.php @@ -15,6 +15,7 @@ class MetricBreakdown extends Model 'description' => 'Resource ID.', 'default' => '', 'example' => '5e5ea5c16897e', + 'required' => false, ]) ->addRule('name', [ 'type' => self::TYPE_STRING, @@ -27,6 +28,13 @@ class MetricBreakdown extends Model 'description' => 'The value of this metric at the timestamp.', 'default' => 0, 'example' => 1, + ]) + ->addRule('estimate', [ + 'type' => self::TYPE_FLOAT, + 'description' => 'The estimated value of this metric at the end of the period.', + 'default' => 0, + 'example' => 1, + 'required' => false, ]); } diff --git a/src/Appwrite/Utopia/Response/Model/Migration.php b/src/Appwrite/Utopia/Response/Model/Migration.php index f70dc37027..3be1d519a6 100644 --- a/src/Appwrite/Utopia/Response/Model/Migration.php +++ b/src/Appwrite/Utopia/Response/Model/Migration.php @@ -59,6 +59,13 @@ class Migration extends Model 'example' => ['user'], 'array' => true ]) + ->addRule('resourceId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Id of the resource to migrate.', + 'default' => '', + 'example' => 'databaseId:collectionId', + 'array' => false + ]) ->addRule('statusCounters', [ 'type' => self::TYPE_JSON, 'description' => 'A group of counters that represent the total progress of the migration.', diff --git a/src/Appwrite/Utopia/Response/Model/Project.php b/src/Appwrite/Utopia/Response/Model/Project.php index 6e01baee84..fbbe062531 100644 --- a/src/Appwrite/Utopia/Response/Model/Project.php +++ b/src/Appwrite/Utopia/Response/Model/Project.php @@ -323,9 +323,9 @@ class Project extends Model } /** - * Get Collection + * Filter document structure * - * @return string + * @return Document */ public function filter(Document $document): Document { diff --git a/src/Appwrite/Utopia/Response/Model/ProviderRepository.php b/src/Appwrite/Utopia/Response/Model/ProviderRepository.php index c133ae3164..518b5de9ee 100644 --- a/src/Appwrite/Utopia/Response/Model/ProviderRepository.php +++ b/src/Appwrite/Utopia/Response/Model/ProviderRepository.php @@ -41,12 +41,6 @@ class ProviderRepository extends Model 'default' => false, 'example' => true, ]) - ->addRule('runtime', [ - 'type' => self::TYPE_STRING, - 'description' => 'Auto-detected runtime suggestion. Empty if getting response of getRuntime().', - 'default' => '', - 'example' => 'node', - ]) ->addRule('pushedAt', [ 'type' => self::TYPE_DATETIME, 'description' => 'Last commit date in ISO 8601 format.', diff --git a/src/Appwrite/Utopia/Response/Model/ProviderRepositoryFramework.php b/src/Appwrite/Utopia/Response/Model/ProviderRepositoryFramework.php new file mode 100644 index 0000000000..24556f4453 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/ProviderRepositoryFramework.php @@ -0,0 +1,40 @@ +<?php + +namespace Appwrite\Utopia\Response\Model; + +use Appwrite\Utopia\Response; + +class ProviderRepositoryFramework extends ProviderRepository +{ + public function __construct() + { + parent::__construct(); + + $this->addRule('framework', [ + 'type' => self::TYPE_STRING, + 'description' => 'Auto-detected framework. Empty if type is not "framework".', + 'default' => '', + 'example' => 'nextjs', + ]); + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'ProviderRepositoryFramework'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_PROVIDER_REPOSITORY_FRAMEWORK; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/ProviderRepositoryRuntime.php b/src/Appwrite/Utopia/Response/Model/ProviderRepositoryRuntime.php new file mode 100644 index 0000000000..ea20eeea47 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/ProviderRepositoryRuntime.php @@ -0,0 +1,40 @@ +<?php + +namespace Appwrite\Utopia\Response\Model; + +use Appwrite\Utopia\Response; + +class ProviderRepositoryRuntime extends ProviderRepository +{ + public function __construct() + { + parent::__construct(); + + $this->addRule('runtime', [ + 'type' => self::TYPE_STRING, + 'description' => 'Auto-detected runtime. Empty if type is not "runtime".', + 'default' => '', + 'example' => 'node-22', + ]); + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'ProviderRepositoryRuntime'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_PROVIDER_REPOSITORY_RUNTIME; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/Rule.php b/src/Appwrite/Utopia/Response/Model/Rule.php index 932591b90f..12903b270e 100644 --- a/src/Appwrite/Utopia/Response/Model/Rule.php +++ b/src/Appwrite/Utopia/Response/Model/Rule.php @@ -34,17 +34,53 @@ class Rule extends Model 'default' => '', 'example' => 'appwrite.company.com', ]) - ->addRule('resourceType', [ + ->addRule('type', [ 'type' => self::TYPE_STRING, - 'description' => 'Action definition for the rule. Possible values are "api", "function", or "redirect"', + 'description' => 'Action definition for the rule. Possible values are "api", "deployment", or "redirect"', + 'default' => '', + 'example' => 'deployment', + ]) + ->addRule('trigger', [ + 'type' => self::TYPE_STRING, + 'description' => 'Defines how the rule was created. Possible values are "manual" or "deployment"', + 'default' => '', + 'example' => 'manual', + ]) + ->addRule('redirectUrl', [ + 'type' => self::TYPE_STRING, + 'description' => 'URL to redirect to. Used if type is "redirect"', + 'default' => '', + 'example' => 'https://appwrite.io/docs', + ]) + ->addRule('redirectStatusCode', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Status code to apply during redirect. Used if type is "redirect"', + 'default' => '', + 'example' => 301, + ]) + ->addRule('deploymentId', [ + 'type' => self::TYPE_STRING, + 'description' => 'ID of deployment. Used if type is "deployment"', + 'default' => '', + 'example' => 'n3u9feiwmf', + ]) + ->addRule('deploymentResourceType', [ + 'type' => self::TYPE_STRING, + 'description' => 'Type of deployment. Possible values are "function", "site". Used if rule\'s type is "deployment".', 'default' => '', 'example' => 'function', ]) - ->addRule('resourceId', [ + ->addRule('deploymentResourceId', [ 'type' => self::TYPE_STRING, - 'description' => 'ID of resource for the action type. If resourceType is "api" or "url", it is empty. If resourceType is "function", it is ID of the function.', + 'description' => 'ID deployment\'s resource. Used if type is "deployment"', 'default' => '', - 'example' => 'myAwesomeFunction', + 'example' => 'n3u9feiwmf', + ]) + ->addRule('deploymentVcsProviderBranch', [ + 'type' => self::TYPE_STRING, + 'description' => 'Name of Git branch that updates rule. Used if type is "deployment"', + 'default' => '', + 'example' => 'function', ]) ->addRule('status', [ 'type' => self::TYPE_STRING, diff --git a/src/Appwrite/Utopia/Response/Model/Site.php b/src/Appwrite/Utopia/Response/Model/Site.php new file mode 100644 index 0000000000..e6e205909b --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/Site.php @@ -0,0 +1,210 @@ +<?php + +namespace Appwrite\Utopia\Response\Model; + +use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Model; + +class Site extends Model +{ + public function __construct() + { + $this + ->addRule('$id', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('$createdAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Site creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('$updatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Site update date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('name', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site name.', + 'default' => '', + 'example' => 'My Site', + ]) + ->addRule('enabled', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Site enabled.', + 'default' => true, + 'example' => false, + ]) + ->addRule('live', [ + 'type' => self::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.', + 'default' => true, + 'example' => false, + ]) + ->addRule('logging', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.', + 'default' => true, + 'example' => false, + ]) + ->addRule('framework', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site framework.', + 'default' => '', + 'example' => 'react', + ]) + ->addRule('deploymentId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site\'s active deployment ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('deploymentCreatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Active deployment creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('deploymentScreenshotLight', [ + 'type' => self::TYPE_STRING, + 'description' => 'Screenshot of active deployment with light theme preference file ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('deploymentScreenshotDark', [ + 'type' => self::TYPE_STRING, + 'description' => 'Screenshot of active deployment with dark theme preference file ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('latestDeploymentId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site\'s latest deployment ID.', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) + ->addRule('latestDeploymentCreatedAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'Latest deployment creation date in ISO 8601 format.', + 'default' => '', + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) + ->addRule('latestDeploymentStatus', [ + 'type' => self::TYPE_STRING, + 'description' => 'Status of latest deployment. Possible values are "waiting", "processing", "building", "ready", and "failed".', + 'default' => '', + 'example' => 'ready', + ]) + ->addRule('vars', [ + 'type' => Response::MODEL_VARIABLE, + 'description' => 'Site variables.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('timeout', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Site request timeout in seconds.', + 'default' => 15, + 'example' => 300, + ]) + ->addRule('installCommand', [ + 'type' => self::TYPE_STRING, + 'description' => 'The install command used to install the site dependencies.', + 'default' => '', + 'example' => 'npm install', + ]) + ->addRule('buildCommand', [ + 'type' => self::TYPE_STRING, + 'description' => 'The build command used to build the site.', + 'default' => '', + 'example' => 'npm run build', + ]) + ->addRule('outputDirectory', [ + 'type' => self::TYPE_STRING, + 'description' => 'The directory where the site build output is located.', + 'default' => '', + 'example' => 'build', + ]) + ->addRule('installationId', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site VCS (Version Control System) installation id.', + 'default' => '', + 'example' => '6m40at4ejk5h2u9s1hboo', + ]) + ->addRule('providerRepositoryId', [ + 'type' => self::TYPE_STRING, + 'description' => 'VCS (Version Control System) Repository ID', + 'default' => '', + 'example' => 'appwrite', + ]) + ->addRule('providerBranch', [ + 'type' => self::TYPE_STRING, + 'description' => 'VCS (Version Control System) branch name', + 'default' => '', + 'example' => 'main', + ]) + ->addRule('providerRootDirectory', [ + 'type' => self::TYPE_STRING, + 'description' => 'Path to site in VCS (Version Control System) repository', + 'default' => '', + 'example' => 'sites/helloWorld', + ]) + ->addRule('providerSilentMode', [ + 'type' => self::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', + 'default' => false, + 'example' => false, + ]) + ->addRule('specification', [ + 'type' => self::TYPE_STRING, + 'description' => 'Machine specification for builds and executions.', + 'default' => APP_COMPUTE_SPECIFICATION_DEFAULT, + 'example' => APP_COMPUTE_SPECIFICATION_DEFAULT, + ]) + ->addRule('buildRuntime', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site build runtime.', + 'default' => '', + 'example' => 'node-22', + ]) + ->addRule('adapter', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site framework adapter.', + 'default' => null, + 'example' => 'static', + ]) + ->addRule('fallbackFile', [ + 'type' => self::TYPE_STRING, + 'description' => 'Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.', + 'default' => null, + 'example' => 'index.html', + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'Site'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_SITE; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/Specification.php b/src/Appwrite/Utopia/Response/Model/Specification.php index a7c7d7389e..4fa7fb9bc7 100644 --- a/src/Appwrite/Utopia/Response/Model/Specification.php +++ b/src/Appwrite/Utopia/Response/Model/Specification.php @@ -32,7 +32,7 @@ class Specification extends Model 'type' => self::TYPE_STRING, 'description' => 'Size slug.', 'default' => '', - 'example' => APP_FUNCTION_SPECIFICATION_DEFAULT + 'example' => APP_COMPUTE_SPECIFICATION_DEFAULT ]); } diff --git a/src/Appwrite/Utopia/Response/Model/TemplateFramework.php b/src/Appwrite/Utopia/Response/Model/TemplateFramework.php new file mode 100644 index 0000000000..ae94ca4425 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/TemplateFramework.php @@ -0,0 +1,89 @@ +<?php + +namespace Appwrite\Utopia\Response\Model; + +use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Model; + +class TemplateFramework extends Model +{ + public function __construct() + { + $this + ->addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Parent framework key.', + 'default' => '', + 'example' => 'sveltekit', + ]) + ->addRule('name', [ + 'type' => self::TYPE_STRING, + 'description' => 'Framework Name.', + 'default' => '', + 'example' => 'SvelteKit' + ]) + ->addRule('installCommand', [ + 'type' => self::TYPE_STRING, + 'description' => 'The install command used to install the dependencies.', + 'default' => '', + 'example' => 'npm install', + ]) + ->addRule('buildCommand', [ + 'type' => self::TYPE_STRING, + 'description' => 'The build command used to build the deployment.', + 'default' => '', + 'example' => 'npm run build', + ]) + ->addRule('outputDirectory', [ + 'type' => self::TYPE_STRING, + 'description' => 'The output directory to store the build output.', + 'default' => '', + 'example' => './build', + ]) + ->addRule('providerRootDirectory', [ + 'type' => self::TYPE_STRING, + 'description' => 'Path to site in VCS (Version Control System) repository', + 'default' => '', + 'example' => './svelte-kit/starter', + ]) + ->addRule('buildRuntime', [ + 'type' => self::TYPE_STRING, + 'description' => 'Runtime used during build step of template.', + 'default' => '', + 'example' => 'node-22', + ]) + ->addRule('adapter', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site framework runtime', + 'default' => '', + 'example' => 'ssr', + ]) + ->addRule('fallbackFile', [ + 'type' => self::TYPE_STRING, + 'description' => 'Fallback file for SPA. Only relevant for static serve runtime.', + 'default' => null, + 'example' => 'index.html', + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'Template Framework'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_TEMPLATE_FRAMEWORK; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/TemplateSite.php b/src/Appwrite/Utopia/Response/Model/TemplateSite.php new file mode 100644 index 0000000000..053742dfdb --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/TemplateSite.php @@ -0,0 +1,116 @@ +<?php + +namespace Appwrite\Utopia\Response\Model; + +use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Model; + +class TemplateSite extends Model +{ + public function __construct() + { + $this + ->addRule('key', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site Template ID.', + 'default' => '', + 'example' => 'starter', + ]) + ->addRule('name', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site Template Name.', + 'default' => '', + 'example' => 'Starter site', + ]) + ->addRule('tagline', [ + 'type' => self::TYPE_STRING, + 'description' => 'Short description of template', + 'default' => '', + 'example' => 'Minimal web app integrating with Appwrite.', + ]) + ->addRule('demoUrl', [ + 'type' => self::TYPE_STRING, + 'description' => 'URL hosting a template demo.', + 'default' => '', + 'example' => 'https://nextjs-starter.appwrite.network/', + ]) + ->addRule('screenshotDark', [ + 'type' => self::TYPE_STRING, + 'description' => 'File URL with preview screenshot in dark theme preference.', + 'default' => '', + 'example' => 'https://cloud.appwrite.io/images/sites/templates/template-for-blog-dark.png', + ]) + ->addRule('screenshotLight', [ + 'type' => self::TYPE_STRING, + 'description' => 'File URL with preview screenshot in light theme preference.', + 'default' => '', + 'example' => 'https://cloud.appwrite.io/images/sites/templates/template-for-blog-light.png', + ]) + ->addRule('useCases', [ + 'type' => self::TYPE_STRING, + 'description' => 'Site use cases.', + 'default' => [], + 'example' => 'Starter', + 'array' => true, + ]) + ->addRule('frameworks', [ + 'type' => Response::MODEL_TEMPLATE_FRAMEWORK, + 'description' => 'List of frameworks that can be used with this template.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('vcsProvider', [ + 'type' => self::TYPE_STRING, + 'description' => 'VCS (Version Control System) Provider.', + 'default' => '', + 'example' => 'github', + ]) + ->addRule('providerRepositoryId', [ + 'type' => self::TYPE_STRING, + 'description' => 'VCS (Version Control System) Repository ID', + 'default' => '', + 'example' => 'templates', + ]) + ->addRule('providerOwner', [ + 'type' => self::TYPE_STRING, + 'description' => 'VCS (Version Control System) Owner.', + 'default' => '', + 'example' => 'appwrite', + ]) + ->addRule('providerVersion', [ + 'type' => self::TYPE_STRING, + 'description' => 'VCS (Version Control System) branch version (tag).', + 'default' => '', + 'example' => 'main', + ]) + ->addRule('variables', [ + 'type' => Response::MODEL_TEMPLATE_VARIABLE, + 'description' => 'Site variables.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'Template Site'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_TEMPLATE_SITE; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/TemplateVariable.php b/src/Appwrite/Utopia/Response/Model/TemplateVariable.php index c992083a87..e196b29032 100644 --- a/src/Appwrite/Utopia/Response/Model/TemplateVariable.php +++ b/src/Appwrite/Utopia/Response/Model/TemplateVariable.php @@ -28,6 +28,12 @@ class TemplateVariable extends Model 'default' => '', 'example' => '512', ]) + ->addRule('secret', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Variable secret flag. Secret variables can only be updated or deleted, but never read.', + 'default' => false, + 'example' => false, + ]) ->addRule('placeholder', [ 'type' => self::TYPE_STRING, 'description' => 'Variable Placeholder.', diff --git a/src/Appwrite/Utopia/Response/Model/UsageBuckets.php b/src/Appwrite/Utopia/Response/Model/UsageBuckets.php index 2f528ac9d1..ee624a29ad 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageBuckets.php +++ b/src/Appwrite/Utopia/Response/Model/UsageBuckets.php @@ -42,6 +42,19 @@ class UsageBuckets extends Model 'example' => [], 'array' => true ]) + ->addRule('imageTransformations', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of files transformations per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('imageTransformationsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of files transformations.', + 'default' => 0, + 'example' => 0, + ]) ; } diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php index eb985baabb..a0fe421f5f 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php @@ -34,6 +34,18 @@ class UsageDatabase extends Model 'default' => 0, 'example' => 0, ]) + ->addRule('databaseReadsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total number of databases reads.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('databaseWritesTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total number of databases writes.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('collections', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated number of collections per period.', @@ -55,6 +67,20 @@ class UsageDatabase extends Model 'example' => [], 'array' => true ]) + ->addRule('databaseReads', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'An array of aggregated number of database reads.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('databaseWrites', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'An array of aggregated number of database writes.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ; } diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php index e0abba8ab8..4e053e5223 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php @@ -40,6 +40,18 @@ class UsageDatabases extends Model 'default' => 0, 'example' => 0, ]) + ->addRule('databasesReadsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total number of databases reads.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('databasesWritesTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total number of databases writes.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('databases', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated number of databases per period.', @@ -68,6 +80,20 @@ class UsageDatabases extends Model 'example' => [], 'array' => true ]) + ->addRule('databasesReads', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'An array of aggregated number of database reads.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('databasesWrites', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'An array of aggregated number of database writes.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ; } diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunction.php b/src/Appwrite/Utopia/Response/Model/UsageFunction.php index ac21c5ae0d..32a23250d4 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunction.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunction.php @@ -34,6 +34,18 @@ class UsageFunction extends Model 'default' => 0, 'example' => 0, ]) + ->addRule('buildsSuccessTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of successful function builds.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('buildsFailedTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of failed function builds.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('buildsStorageTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'total aggregated sum of function builds storage.', @@ -46,6 +58,12 @@ class UsageFunction extends Model 'default' => 0, 'example' => 0, ]) + ->addRule('buildsTimeAverage', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Average builds compute time.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('buildsMbSecondsTotal', [ 'type' => self::TYPE_INTEGER, 'description' => 'Total aggregated sum of function builds mbSeconds.', @@ -133,6 +151,20 @@ class UsageFunction extends Model 'example' => [], 'array' => true ]) + ->addRule('buildsSuccess', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of successful builds per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('buildsFailed', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of failed builds per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ; } diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php index 90327a7e8a..6dc03c6293 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php @@ -97,6 +97,18 @@ class UsageFunctions extends Model 'example' => [], 'array' => true ]) + ->addRule('buildsSuccessTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of successful function builds.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('buildsFailedTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of failed function builds.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('builds', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated number of functions build per period.', @@ -146,6 +158,20 @@ class UsageFunctions extends Model 'example' => [], 'array' => true ]) + ->addRule('buildsSuccess', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of successful function builds per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('buildsFailed', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of failed function builds per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) ; } diff --git a/src/Appwrite/Utopia/Response/Model/UsageProject.php b/src/Appwrite/Utopia/Response/Model/UsageProject.php index 17d9271f04..395b19b7cd 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageProject.php +++ b/src/Appwrite/Utopia/Response/Model/UsageProject.php @@ -82,6 +82,18 @@ class UsageProject extends Model 'default' => 0, 'example' => 0, ]) + ->addRule('databasesReadsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total number of databases reads.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('databasesWritesTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total number of databases writes.', + 'default' => 0, + 'example' => 0, + ]) ->addRule('requests', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated number of requests per period.', @@ -152,6 +164,52 @@ class UsageProject extends Model 'example' => [], 'array' => true ]) + ->addRule('authPhoneTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of phone auth.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('authPhoneEstimate', [ + 'type' => self::TYPE_FLOAT, + 'description' => 'Estimated total aggregated cost of phone auth.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('authPhoneCountryBreakdown', [ + 'type' => Response::MODEL_METRIC_BREAKDOWN, + 'description' => 'Aggregated breakdown in totals of phone auth by country.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('databasesReads', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'An array of aggregated number of database reads.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('databasesWrites', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'An array of aggregated number of database writes.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('imageTransformations', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'An array of aggregated number of image transformations.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('imageTransformationsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of image transformations.', + 'default' => 0, + 'example' => 0, + ]) ; } diff --git a/src/Appwrite/Utopia/Response/Model/UsageSite.php b/src/Appwrite/Utopia/Response/Model/UsageSite.php new file mode 100644 index 0000000000..c45dc831cd --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/UsageSite.php @@ -0,0 +1,74 @@ +<?php + +namespace Appwrite\Utopia\Response\Model; + +use Appwrite\Utopia\Response; + +class UsageSite extends UsageFunction +{ + public function __construct() + { + parent::__construct(); + $this + ->addRule('requestsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of requests.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('requests', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of requests per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('inboundTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated inbound bandwidth.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('inbound', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of inbound bandwidth per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('outboundTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated outbound bandwidth.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('outbound', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of outbound bandwidth per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'UsageSite'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_USAGE_SITE; + } +} diff --git a/src/Appwrite/Utopia/Response/Model/UsageSites.php b/src/Appwrite/Utopia/Response/Model/UsageSites.php new file mode 100644 index 0000000000..74435b332c --- /dev/null +++ b/src/Appwrite/Utopia/Response/Model/UsageSites.php @@ -0,0 +1,89 @@ +<?php + +namespace Appwrite\Utopia\Response\Model; + +use Appwrite\Utopia\Response; + +class UsageSites extends UsageFunctions +{ + public function __construct() + { + parent::__construct(); + $this + ->removeRule('functionsTotal') + ->removeRule('functions') + ->addRule('sitesTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of sites.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('sites', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of sites per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('requestsTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated number of requests.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('requests', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of requests per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('inboundTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated inbound bandwidth.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('inbound', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of inbound bandwidth per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ->addRule('outboundTotal', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Total aggregated outbound bandwidth.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('outbound', [ + 'type' => Response::MODEL_METRIC, + 'description' => 'Aggregated number of outbound bandwidth per period.', + 'default' => [], + 'example' => [], + 'array' => true + ]) + ; + } + + /** + * Get Name + * + * @return string + */ + public function getName(): string + { + return 'UsageSites'; + } + + /** + * Get Type + * + * @return string + */ + public function getType(): string + { + return Response::MODEL_USAGE_SITES; + } +} diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php index 18379f1099..62f6ef61d0 100644 --- a/src/Appwrite/Vcs/Comment.php +++ b/src/Appwrite/Vcs/Comment.php @@ -9,10 +9,11 @@ use Utopia\System\System; class Comment { + // TODO: Add more tips protected array $tips = [ - 'Appwrite has a Discord community with over 16 000 members. [Come join us!](https://appwrite.io/discord)', - 'You can use [Avatars API](https://appwrite.io/docs/client/avatars?sdk=web-default#avatarsGetQR) to generate QR code for any text or URLs', - '[Cursor pagination](https://appwrite.io/docs/pagination#cursor-pagination) performs better than offset pagination when loading further pages', + 'Appwrite has a Discord community with over 16 000 members.', + 'You can use Avatars API to generate QR code for any text or URLs.', + 'Cursor pagination performs better than offset pagination when loading further pages.', ]; protected string $statePrefix = '[appwrite]: #'; @@ -27,19 +28,21 @@ class Comment return \count($this->builds) === 0; } - public function addBuild(Document $project, Document $function, string $buildStatus, string $deploymentId, array $action): void + public function addBuild(Document $project, Document $resource, string $resourceType, string $buildStatus, string $deploymentId, array $action, string $previewUrl): void { // Unique index - $id = $project->getId() . '_' . $function->getId(); + $id = $project->getId() . '_' . $resource->getId(); $this->builds[$id] = [ 'projectName' => $project->getAttribute('name'), 'projectId' => $project->getId(), - 'functionName' => $function->getAttribute('name'), - 'functionId' => $function->getId(), + 'resourceName' => $resource->getAttribute('name'), + 'resourceId' => $resource->getId(), + 'resourceType' => $resourceType, 'buildStatus' => $buildStatus, 'deploymentId' => $deploymentId, 'action' => $action, + 'previewUrl' => $previewUrl, ]; } @@ -55,75 +58,152 @@ class Comment if (!\array_key_exists($build['projectId'], $projects)) { $projects[$build['projectId']] = [ 'name' => $build['projectName'], - 'functions' => [] + 'function' => [], + 'site' => [] ]; } - $projects[$build['projectId']]['functions'][$build['functionId']] = [ - 'name' => $build['functionName'], - 'status' => $build['buildStatus'], - 'deploymentId' => $build['deploymentId'], - 'action' => $build['action'], - ]; + if ($build['resourceType'] === 'site') { + $projects[$build['projectId']]['site'][$build['resourceId']] = [ + 'name' => $build['resourceName'], + 'status' => $build['buildStatus'], + 'deploymentId' => $build['deploymentId'], + 'action' => $build['action'], + 'previewUrl' => $build['previewUrl'], + ]; + } elseif ($build['resourceType'] === 'function') { + $projects[$build['projectId']]['function'][$build['resourceId']] = [ + 'name' => $build['resourceName'], + 'status' => $build['buildStatus'], + 'deploymentId' => $build['deploymentId'], + 'action' => $build['action'], + ]; + } } + $i = 0; foreach ($projects as $projectId => $project) { - $text .= "**{$project['name']}** `{$projectId}`\n\n"; - $text .= "| Function | ID | Status | Action |\n"; - $text .= "| :- | :- | :- | :- |\n"; - $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; $hostname = System::getEnv('_APP_DOMAIN'); - foreach ($project['functions'] as $functionId => $function) { - if ($function['status'] === 'waiting' || $function['status'] === 'processing' || $function['status'] === 'building') { - $text .= "**Your function deployment is in progress. Please check back in a few minutes for the updated status.**\n\n"; - } elseif ($function['status'] === 'ready') { - $text .= "**Your function has been successfully deployed.**\n\n"; - } else { - $text .= "**Your function deployment has failed. Please check the logs for more details and retry.**\n\n"; + $text .= "## {$project['name']}\n\n"; + $text .= "Project ID: `{$projectId}`\n\n"; + + $isOpen = $i === 0; + + if (\count($project['site']) > 0) { + $text .= "<details" . ($isOpen ? ' open' : '') . ">\n"; + $text .= "<summary>Sites (" . \count($project['site']) . ")</summary>\n\n"; + $text .= "<br>\n\n"; + + $text .= "| Site | Status | Logs | Preview | QR\n"; + $text .= "| :- | :- | :- | :- | :- |\n"; + + 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; + + $status = match ($site['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_', + 'ready' => $this->generatImage($pathLight, $pathDark, 'Ready', 85) . ' _Ready_', + 'failed' => $this->generatImage($pathLight, $pathDark, 'Failed', 85) . ' _Failed_', + }; + + if ($site['action']['type'] === 'logs') { + $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $projectId . '/sites/site-' . $siteId . '/deployments/deployment-' . $site['deploymentId'] . ')'; + } else { + $action = '[Authorize](' . $site['action']['url'] . ')'; + } + + $qrImagePathLight = '/images/vcs/qr-light.svg'; + $qrImagePathDark = '/images/vcs/qr-dark.svg'; + + $consoleUrl = $protocol . '://' . $hostname . '/v1/avatars/qr?text=' . \urlencode($site['previewUrl']); + $qr = '[' . $this->generatImage($qrImagePathLight, $qrImagePathDark, 'QR Code', 28) . '](' . $consoleUrl . ')'; + + $preview = '[Preview URL](' . $site['previewUrl'] . ')'; + + $text .= "|  **{$site['name']}**<br>`$siteId`"; + $text .= "| {$status}"; + $text .= "| {$action}"; + $text .= "| {$preview}"; + $text .= "| {$qr}"; + $text .= "|\n"; } - $text .= "Project name: **{$project['name']}** \nProject ID: `{$projectId}`\n\n"; - $text .= "| Function | ID | Status | Action |\n"; - $text .= "| :- | :- | :- | :- |\n"; - - $generateImage = function (string $status) use ($protocol, $hostname) { - $extention = $status === 'building' ? 'gif' : 'png'; - $imagesUrl = $protocol . '://' . $hostname . '/images/vcs/'; - $imageUrl = '<picture><source media="(prefers-color-scheme: dark)" srcset="' . $imagesUrl . 'status-' . $status . '-dark.' . $extention . '"><img alt="' . $status . '" height="25" align="center" src="' . $imagesUrl . 'status-' . $status . '-light.' . $extention . '"></picture>'; - - return $imageUrl; - }; - - $status = match ($function['status']) { - 'waiting' => $generateImage('waiting') . ' Waiting to build', - 'processing' => $generateImage('processing') . ' Processing', - 'building' => $generateImage('building') . ' Building', - 'ready' => $generateImage('ready') . ' Ready', - 'failed' => $generateImage('failed') . ' Failed', - }; - - if ($function['action']['type'] === 'logs') { - $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $projectId . '/functions/function-' . $functionId . '/deployment-' . $function['deploymentId'] . ')'; - } else { - $action = '[Authorize](' . $function['action']['url'] . ')'; - } - - $text .= "| {$function['name']} | `{$functionId}` | {$status} | {$action} |\n"; + $text .= "\n</details>\n\n"; } - $text .= "\n\n"; + if (\count($project['function']) > 0) { + $text .= "<details" . ($isOpen ? ' open' : '') . ">\n"; + $text .= "<summary>Functions (" . \count($project['function']) . ")</summary>\n\n"; + $text .= "<br>\n\n"; + $text .= "| Function | ID | Status | Logs |\n"; + $text .= "| :- | :- | :- | :- |\n"; + + foreach ($project['function'] as $functionId => $function) { + $extension = $site['status'] === 'building' ? 'gif' : 'png'; + + $pathLight = '/images/vcs/status-' . $site['status'] . '-light.' . $extension; + $pathDark = '/images/vcs/status-' . $site['status'] . '-dark.' . $extension; + + $status = match ($site['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_', + 'ready' => $this->generatImage($pathLight, $pathDark, 'Ready', 85) . ' _Ready_', + 'failed' => $this->generatImage($pathLight, $pathDark, 'Failed', 85) . ' _Failed_', + }; + + if ($function['action']['type'] === 'logs') { + $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $projectId . '/functions/function-' . $functionId . '/deployment-' . $function['deploymentId'] . ')'; + } else { + $action = '[Authorize](' . $function['action']['url'] . ')'; + } + + $text .= "|  **{$function['name']}**<br>`$functionId`"; + $text .= "| {$status}"; + $text .= "| {$action}"; + $text .= "|\n"; + } + + $text .= "</details>\n\n"; + } + + $text .= "</details>\n\n"; + + $isLast = $i === \count($projects) - 1; + + if (\count($projects) > 1 && $isLast) { + $text .= "---\n\n"; + } + + $i++; } - $functionUrl = $protocol . '://' . $hostname . '/console/project-' . $projectId . '/functions/function-' . $functionId; - $text .= "Only deployments on the production branch are activated automatically. If you'd like to activate this deployment, navigate to [your deployments]($functionUrl). Learn more about Appwrite [Function deployments](https://appwrite.io/docs/functions).\n\n"; $tip = $this->tips[array_rand($this->tips)]; - $text .= "> **💡 Did you know?** \n " . $tip . "\n\n"; + $text .= "\n<br>\n\n> [!NOTE]\n> $tip\n\n"; return $text; } + 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'); + + $imageLight = $protocol . '://' . $hostname . $pathLight; + $imageDark = $protocol . '://' . $hostname . $pathDark; + + $imageUrl = '<picture><source media="(prefers-color-scheme: dark)" srcset="' . $imageDark . '"><img alt="' . $alt . '" width="' . $width . '" align="center" src="' . $imageLight . '"></picture>'; + + return $imageUrl; + } + public function parseComment(string $comment): self { $state = \explode("\n", $comment)[0] ?? ''; diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index c230cfb664..c381ceeae3 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -21,17 +21,19 @@ class Executor private bool $selfSigned = false; - private string $endpoint; + /** + * @var callable(string, string): string $endpoint + */ + private $endpointSelector; protected array $headers; - public function __construct(string $endpoint) + /** + * @param callable(string, string): string $endpointSelector + */ + public function __construct(callable $endpointSelector) { - if (!filter_var($endpoint, FILTER_VALIDATE_URL)) { - throw new Exception('Unsupported endpoint'); - } - - $this->endpoint = $endpoint; + $this->endpointSelector = $endpointSelector; $this->headers = [ 'content-type' => 'application/json', 'authorization' => 'Bearer ' . System::getEnv('_APP_EXECUTOR_SECRET', ''), @@ -62,19 +64,20 @@ class Executor string $version, float $cpus, int $memory, + int $timeout, bool $remove = false, string $entrypoint = '', string $destination = '', array $variables = [], string $command = null, + string $outputDirectory = '' ) { $runtimeId = "$projectId-$deploymentId-build"; $route = "/runtimes"; - $timeout = (int) System::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); // Remove after migration - if ($version == 'v3') { - $version = 'v4'; + if ($version === 'v3' || $version === 'v4') { + $version = 'v5'; } $params = [ @@ -90,9 +93,11 @@ class Executor 'memory' => $memory, 'version' => $version, 'timeout' => $timeout, + 'outputDirectory' => $outputDirectory ]; - $response = $this->call(self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout); + $endpoint = $this->selectEndpoint($projectId, $deploymentId); + $response = $this->call($endpoint, self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout); $status = $response['headers']['status-code']; if ($status >= 400) { @@ -113,17 +118,17 @@ class Executor public function getLogs( string $deploymentId, string $projectId, + string $timeout, callable $callback ) { - $timeout = (int) System::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); - $runtimeId = "$projectId-$deploymentId-build"; $route = "/runtimes/{$runtimeId}/logs"; $params = [ 'timeout' => $timeout ]; - $this->call(self::METHOD_GET, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout, $callback); + $endpoint = $this->selectEndpoint($projectId, $deploymentId); + $this->call($endpoint, self::METHOD_GET, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout, $callback); } /** @@ -134,15 +139,21 @@ class Executor * @param string $projectId * @param string $deploymentId */ - public function deleteRuntime(string $projectId, string $deploymentId) + public function deleteRuntime(string $projectId, string $deploymentId, string $suffix = '') { - $runtimeId = "$projectId-$deploymentId"; + $runtimeId = "$projectId-$deploymentId" . $suffix; $route = "/runtimes/$runtimeId"; - $response = $this->call(self::METHOD_DELETE, $route, [ + $endpoint = $this->selectEndpoint($projectId, $deploymentId); + $response = $this->call($endpoint, self::METHOD_DELETE, $route, [ 'x-opr-addressing-method' => 'broadcast' ], [], true, 30); + // Temporary fix for race condition + if ($response['headers']['status-code'] === 500 && \str_contains($response['body']['message'], 'already in progress')) { + return true; // OK, removal already in progress + } + $status = $response['headers']['status-code']; if ($status >= 400) { $message = \is_string($response['body']) ? $response['body'] : $response['body']['message']; @@ -195,8 +206,8 @@ class Executor $route = '/runtimes/' . $runtimeId . '/executions'; // Remove after migration - if ($version == 'v3') { - $version = 'v4'; + if ($version === 'v3' || $version === 'v4') { + $version = 'v5'; } $params = [ @@ -227,7 +238,8 @@ class Executor $requestTimeout = $timeout + 15; } - $response = $this->call(self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId, 'content-type' => 'multipart/form-data', 'accept' => 'multipart/form-data' ], $params, true, $requestTimeout); + $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); $status = $response['headers']['status-code']; if ($status >= 400) { @@ -235,7 +247,11 @@ class Executor throw new \Exception($message, $status); } - $response['body']['headers'] = \json_decode($response['body']['headers'] ?? '{}', true); + $headers = $response['body']['headers'] ?? []; + if (is_string($headers)) { + $headers = \json_decode($headers, true); + } + $response['body']['headers'] = $headers; $response['body']['statusCode'] = \intval($response['body']['statusCode'] ?? 500); $response['body']['duration'] = \floatval($response['body']['duration'] ?? 0); $response['body']['startTime'] = \floatval($response['body']['startTime'] ?? \microtime(true)); @@ -243,6 +259,32 @@ class Executor return $response['body']; } + public function createCommand( + string $deploymentId, + string $projectId, + string $command, + int $timeout + ) { + $runtimeId = "$projectId-$deploymentId-build"; + $route = "/runtimes/$runtimeId/commands"; + + $params = [ + 'command' => $command, + 'timeout' => $timeout + ]; + + $endpoint = $this->selectEndpoint($projectId, $deploymentId); + $response = $this->call($endpoint, self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout); + + $status = $response['headers']['status-code']; + if ($status >= 400) { + $message = \is_string($response['body']) ? $response['body'] : $response['body']['message']; + throw new \Exception($message, $status); + } + + return $response['body']; + } + /** * Call * @@ -256,10 +298,10 @@ class Executor * @return array|string * @throws Exception */ - public function call(string $method, string $path = '', array $headers = [], array $params = [], bool $decode = true, int $timeout = 15, callable $callback = null) + private function call(string $endpoint, string $method, string $path = '', array $headers = [], array $params = [], bool $decode = true, int $timeout = 15, callable $callback = null) { $headers = array_merge($this->headers, $headers); - $ch = curl_init($this->endpoint . $path . (($method == self::METHOD_GET && !empty($params)) ? '?' . http_build_query($params) : '')); + $ch = curl_init($endpoint . $path . (($method == self::METHOD_GET && !empty($params)) ? '?' . http_build_query($params) : '')); $responseHeaders = []; $responseStatus = -1; $responseType = ''; @@ -422,4 +464,9 @@ class Executor return $output; } + + private function selectEndpoint(string $projectId, string $deploymentId): string + { + return call_user_func($this->endpointSelector, $projectId, $deploymentId); + } } diff --git a/tests/e2e/Client.php b/tests/e2e/Client.php index dc80808b14..278d1cd0d5 100644 --- a/tests/e2e/Client.php +++ b/tests/e2e/Client.php @@ -164,7 +164,7 @@ class Client * @return array * @throws Exception */ - public function call(string $method, string $path = '', array $headers = [], mixed $params = [], bool $decode = true): array + public function call(string $method, string $path = '', array $headers = [], mixed $params = [], bool $decode = true, bool $followRedirects = true): array { $headers = array_merge($this->headers, $headers); $ch = curl_init($this->endpoint . $path . (($method == self::METHOD_GET && !empty($params)) ? '?' . http_build_query($params) : '')); @@ -192,7 +192,7 @@ class Client curl_setopt($ch, CURLOPT_PATH_AS_IS, 1); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $followRedirects); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'); curl_setopt($ch, CURLOPT_HTTPHEADER, $formattedHeaders); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index c50a15fd3f..72bf747576 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -2,7 +2,7 @@ namespace Tests\E2E\General; -use Appwrite\Functions\Specification; +use Appwrite\Platform\Modules\Compute\Specification; use Appwrite\Tests\Retry; use CURLFile; use DateTime; @@ -12,18 +12,72 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; use Tests\E2E\Services\Functions\FunctionsBase; +use Tests\E2E\Services\Sites\SitesBase; +use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; +use Utopia\System\System; class UsageTest extends Scope { use ProjectCustom; use SideServer; use FunctionsBase; + use SitesBase { + FunctionsBase::createDeployment insteadof SitesBase; + FunctionsBase::setupDeployment insteadof SitesBase; + FunctionsBase::createVariable insteadof SitesBase; + FunctionsBase::getVariable insteadof SitesBase; + FunctionsBase::listVariables insteadof SitesBase; + FunctionsBase::updateVariable insteadof SitesBase; + FunctionsBase::deleteVariable insteadof SitesBase; + FunctionsBase::getDeployment insteadof SitesBase; + FunctionsBase::listDeployments insteadof SitesBase; + FunctionsBase::deleteDeployment insteadof SitesBase; + FunctionsBase::setupDuplicateDeployment insteadof SitesBase; + FunctionsBase::createDuplicateDeployment insteadof SitesBase; + FunctionsBase::createTemplateDeployment insteadof SitesBase; + FunctionsBase::getUsage insteadof SitesBase; + FunctionsBase::getTemplate insteadof SitesBase; + FunctionsBase::getDeploymentDownload insteadof SitesBase; + FunctionsBase::cancelDeployment insteadof SitesBase; + FunctionsBase::listSpecifications insteadof SitesBase; + SitesBase::createDeployment as createDeploymentSite; + SitesBase::setupDeployment as setupDeploymentSite; + SitesBase::createVariable as createVariableSite; + SitesBase::getVariable as getVariableSite; + SitesBase::listVariables as listVariablesSite; + SitesBase::listVariables as listVariablesSite; + SitesBase::updateVariable as updateVariableSite; + SitesBase::updateVariable as updateVariableSite; + SitesBase::deleteVariable as deleteVariableSite; + SitesBase::deleteVariable as deleteVariableSite; + SitesBase::getDeployment as getDeploymentSite; + SitesBase::getDeployment as getDeploymentSite; + SitesBase::listDeployments as listDeploymentsSite; + SitesBase::listDeployments as listDeploymentsSite; + SitesBase::deleteDeployment as deleteDeploymentSite; + SitesBase::deleteDeployment as deleteDeploymentSite; + SitesBase::setupDuplicateDeployment as setupDuplicateDeploymentSite; + SitesBase::setupDuplicateDeployment as setupDuplicateDeploymentSite; + SitesBase::createDuplicateDeployment as createDuplicateDeploymentSite; + SitesBase::createDuplicateDeployment as createDuplicateDeploymentSite; + SitesBase::createTemplateDeployment as createTemplateDeploymentSite; + SitesBase::createTemplateDeployment as createTemplateDeploymentSite; + SitesBase::getUsage as getUsageSite; + SitesBase::getUsage as getUsageSite; + SitesBase::getTemplate as getTemplateSite; + SitesBase::getTemplate as getTemplateSite; + SitesBase::getDeploymentDownload as getDeploymentDownloadSite; + SitesBase::getDeploymentDownload as getDeploymentDownloadSite; + SitesBase::cancelDeployment as cancelDeploymentSite; + SitesBase::cancelDeployment as cancelDeploymentSite; + SitesBase::listSpecifications as listSpecificationsSite; + } - private const WAIT = 35; + private const WAIT = 5; private const CREATE = 20; protected string $projectId; @@ -52,6 +106,13 @@ class UsageTest extends Scope } } + public static function getYesterday(): string + { + $date = new DateTime(); + $date->modify('-1 day'); + return $date->format(self::$formatTz); + } + public static function getToday(): string { $date = new DateTime(); @@ -127,8 +188,6 @@ class UsageTest extends Scope #[Retry(count: 1)] public function testUsersStats(array $data): array { - sleep(self::WAIT); - $requestsTotal = $data['requestsTotal']; $response = $this->client->call( @@ -143,7 +202,7 @@ class UsageTest extends Scope ); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(22, count($response['body'])); + $this->assertEquals(31, count($response['body'])); $this->validateDates($response['body']['network']); $this->validateDates($response['body']['requests']); $this->validateDates($response['body']['users']); @@ -302,7 +361,7 @@ class UsageTest extends Scope /** * @depends testPrepareStorageStats */ - #[Retry(count: 1)] + #[Retry(count: 10)] public function testStorageStats(array $data): array { $bucketId = $data['bucketId']; @@ -311,8 +370,6 @@ class UsageTest extends Scope $storageTotal = $data['storageTotal']; $filesTotal = $data['filesTotal']; - sleep(self::WAIT); - $response = $this->client->call( Client::METHOD_GET, '/project/usage', @@ -324,7 +381,7 @@ class UsageTest extends Scope ] ); - $this->assertEquals(22, count($response['body'])); + $this->assertEquals(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']); @@ -467,10 +524,10 @@ class UsageTest extends Scope $this->assertEquals('name', $response['body']['key']); - $requestsTotal += 1; - sleep(self::WAIT); + $requestsTotal += 1; + for ($i = 0; $i < self::CREATE; $i++) { $name = uniqid() . ' collection'; @@ -545,7 +602,7 @@ class UsageTest extends Scope ] ); - $this->assertEquals(22, count($response['body'])); + $this->assertEquals(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']); @@ -702,8 +759,6 @@ class UsageTest extends Scope // $this->assertEquals(201, $response['headers']['status-code']); // } - // sleep(self::WAIT); - // for ($i = 0; $i < 3; $i++) { // try { // $newProjectMetrics = $this->client->call( @@ -745,7 +800,6 @@ class UsageTest extends Scope // if ($i === 2) { // throw $e; // } - // sleep(self::WAIT); // continue; // } // } @@ -785,8 +839,6 @@ class UsageTest extends Scope // $this->assertEquals(204, $response['headers']['status-code']); // } - // sleep(self::WAIT); - // for ($i = 0; $i < 3; $i++) { // try { // $newProjectMetrics = $this->client->call( @@ -828,7 +880,6 @@ class UsageTest extends Scope // if ($i === 2) { // throw $e; // } - // sleep(self::WAIT); // continue; // } // } @@ -883,37 +934,23 @@ class UsageTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $response = $this->client->call( - Client::METHOD_POST, - '/functions/' . $functionId . '/deployments', - array_merge([ - 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'] - ], $this->getHeaders()), - [ - 'entrypoint' => 'index.php', - 'code' => $this->packageFunction('php'), - 'activate' => true, - ] - ); - - $deploymentId = $response['body']['$id'] ?? ''; - - $this->assertEquals(202, $response['headers']['status-code']); - $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); - $this->assertEquals('index.php', $response['body']['entrypoint']); - - // Wait for deployment to build. - sleep(self::WAIT + 20); + $deploymentId = $this->setupDeployment($functionId, [ + 'entrypoint' => 'index.php', + 'code' => $this->packageFunction('php'), + 'activate' => true, + ]); + $this->assertNotEmpty($deploymentId); $response = $this->client->call( Client::METHOD_PATCH, - '/functions/' . $functionId . '/deployments/' . $deploymentId, + '/functions/' . $functionId . '/deployment', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'] ], $this->getHeaders()), + [ + 'deploymentId' => $deploymentId, + ], ); $this->assertEquals(200, $response['headers']['status-code']); @@ -921,7 +958,7 @@ class UsageTest extends Scope $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$updatedAt'])); - $this->assertEquals($deploymentId, $response['body']['deployment']); + $this->assertEquals($deploymentId, $response['body']['deploymentId']); $response = $this->client->call( Client::METHOD_POST, @@ -1020,8 +1057,6 @@ class UsageTest extends Scope $executionTime = $data['executionTime']; $executions = $data['executions']; - sleep(self::WAIT); - $response = $this->client->call( Client::METHOD_GET, '/functions/' . $functionId . '/usage?range=30d', @@ -1029,7 +1064,7 @@ class UsageTest extends Scope ); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(19, count($response['body'])); + $this->assertEquals(24, count($response['body'])); $this->assertEquals('30d', $response['body']['range']); $this->assertIsArray($response['body']['deployments']); $this->assertIsArray($response['body']['deploymentsStorage']); @@ -1054,7 +1089,7 @@ class UsageTest extends Scope ); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(21, count($response['body'])); + $this->assertEquals(25, count($response['body'])); $this->assertEquals($response['body']['range'], '30d'); $this->assertIsArray($response['body']['functions']); $this->assertIsArray($response['body']['deployments']); @@ -1075,6 +1110,145 @@ class UsageTest extends Scope return $data; } + + public function testPrepareSitesStats(): array + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + $deployment = $this->createDeploymentSite($siteId, [ + 'siteId' => $siteId, + 'code' => $this->packageSite('static'), + 'activate' => true, + ]); + + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + $this->assertEquals('waiting', $deployment['body']['status']); + $this->assertEquals(true, (new DatetimeValidator())->isValid($deployment['body']['$createdAt'])); + + $deploymentIdActive = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($siteId, $deploymentIdActive) { + $deployment = $this->getDeploymentSite($siteId, $deploymentIdActive); + + $this->assertEquals('ready', $deployment['body']['status']); + }, 50000, 500); + + $deployment = $this->createDeploymentSite($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'false' + ]); + + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + + $deploymentIdInactive = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($siteId, $deploymentIdInactive) { + $deployment = $this->getDeploymentSite($siteId, $deploymentIdInactive); + + $this->assertEquals('ready', $deployment['body']['status']); + }, 50000, 500); + + $site = $this->getSite($siteId); + + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentIdActive, $site['body']['deploymentId']); + $this->assertNotEquals($deploymentIdInactive, $site['body']['deploymentId']); + + $data = [ + 'siteId' => $siteId, + 'deployments' => 2, + 'deploymentsSuccess' => 2, + 'deploymentsFailed' => 0 + ]; + + return $data; + } + + /** @depends testPrepareSitesStats */ + #[Retry(count: 1)] + public function testSitesStats(array $data) + { + $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']); + + $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 */ public function testCustomDomainsFunctionStats(array $data): void { @@ -1090,22 +1264,24 @@ class UsageTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); - $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => [ - Query::equal('resourceId', [$functionId])->toString(), - Query::equal('resourceType', ['function'])->toString(), + $rule = $this->client->call( + Client::METHOD_POST, + '/proxy/rules/function', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), + [ + 'domain' => 'test-' . ID::unique() . System::getEnv('_APP_DOMAIN_FUNCTIONS'), + 'functionId' => $functionId, ], - ]); + ); - $this->assertEquals(200, $rules['headers']['status-code']); - $this->assertEquals(1, $rules['body']['total']); - $this->assertCount(1, $rules['body']['rules']); - $this->assertNotEmpty($rules['body']['rules'][0]['domain']); + $this->assertEquals(201, $rule['headers']['status-code']); + $this->assertNotEmpty($rule['body']['$id']); + $this->assertNotEmpty($rule['body']['domain']); - $domain = $rules['body']['rules'][0]['domain']; + $domain = $rule['body']['domain']; $response = $this->client->call( Client::METHOD_GET, @@ -1114,7 +1290,7 @@ class UsageTest extends Scope ); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(19, count($response['body'])); + $this->assertEquals(24, count($response['body'])); $this->assertEquals('30d', $response['body']['range']); $functionsMetrics = $response['body']; @@ -1145,52 +1321,40 @@ class UsageTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); - sleep(self::WAIT + 20); $tries = 0; - while (true) { - try { - // Compare new values with old values - $response = $this->client->call( - Client::METHOD_GET, - '/functions/' . $functionId . '/usage?range=30d', - $this->getConsoleHeaders() - ); + $this->assertEventually(function () use ($functionId, $functionsMetrics, $projectMetrics) { + // Compare new values with old values + $response = $this->client->call( + Client::METHOD_GET, + '/functions/' . $functionId . '/usage?range=30d', + $this->getConsoleHeaders() + ); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(19, 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']); - // Check if the new values are greater than the old values - $this->assertEquals($functionsMetrics['executionsTotal'] + 1, $response['body']['executionsTotal']); - $this->assertGreaterThan($functionsMetrics['executionsTimeTotal'], $response['body']['executionsTimeTotal']); - $this->assertGreaterThan($functionsMetrics['executionsMbSecondsTotal'], $response['body']['executionsMbSecondsTotal']); + // Check if the new values are greater than the old values + $this->assertEquals($functionsMetrics['executionsTotal'] + 1, $response['body']['executionsTotal']); + $this->assertGreaterThan($functionsMetrics['executionsTimeTotal'], $response['body']['executionsTimeTotal']); + $this->assertGreaterThan($functionsMetrics['executionsMbSecondsTotal'], $response['body']['executionsMbSecondsTotal']); - $response = $this->client->call( - Client::METHOD_GET, - '/project/usage', - $this->getConsoleHeaders(), - [ - 'period' => '1h', - 'startDate' => self::getToday(), - 'endDate' => self::getTomorrow(), - ] - ); + $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->assertEquals($projectMetrics['executionsTotal'] + 1, $response['body']['executionsTotal']); - $this->assertGreaterThan($projectMetrics['executionsMbSecondsTotal'], $response['body']['executionsMbSecondsTotal']); - - break; - } catch (ExpectationFailedException $th) { - if ($tries >= 5) { - throw $th; - } else { - $tries++; - sleep(5); - } - } - } + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($projectMetrics['executionsTotal'] + 1, $response['body']['executionsTotal']); + $this->assertGreaterThan($projectMetrics['executionsMbSecondsTotal'], $response['body']['executionsMbSecondsTotal']); + }); } public function tearDown(): void diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index 7f84ace6f2..a1616f2f74 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -4,6 +4,7 @@ namespace Tests\E2E\Scopes; use Tests\E2E\Client; use Utopia\Database\Helpers\ID; +use Utopia\System\System; trait ProjectCustom { @@ -42,7 +43,7 @@ trait ProjectCustom 'x-appwrite-project' => 'console', ], [ 'projectId' => ID::unique(), - 'region' => 'default', + 'region' => System::getEnv('_APP_REGION', 'default'), 'name' => 'Demo Project', 'teamId' => $team['body']['$id'], 'description' => 'Demo Project Description', @@ -74,10 +75,16 @@ trait ProjectCustom 'files.write', 'buckets.read', 'buckets.write', + 'sites.read', + 'sites.write', 'functions.read', 'functions.write', + 'sites.read', + 'sites.write', 'execution.read', 'execution.write', + 'log.read', + 'log.write', 'locale.read', 'avatars.read', 'health.read', diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index cca27cc3be..daa5bcbff8 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -277,6 +277,7 @@ class AccountCustomClientTest extends Scope { sleep(5); $session = $data['session'] ?? ''; + /** * Test for SUCCESS */ @@ -2307,6 +2308,60 @@ class AccountCustomClientTest extends Scope $this->assertNotEmpty($response['body']['$id']); $this->assertNotEmpty($response['body']['expire']); $this->assertEmpty($response['body']['secret']); + $this->assertEquals('browser', $response['body']['clientType']); + $this->assertEquals('CH', $response['body']['clientCode']); + $this->assertEquals('Chrome', $response['body']['clientName']); + + // Forwarded User Agent with API Key + $response = $this->client->call(Client::METHOD_POST, '/users/' . $data['id'] . '/tokens', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'expire' => 60 + ]); + + $userId = $response['body']['userId']; + $secret = $response['body']['secret']; + + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/token', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-forwarded-user-agent' => 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36' + ], [ + 'userId' => $userId, + 'secret' => $secret + ]); + + $this->assertEquals('browser', $response['body']['clientType']); + $this->assertEquals('CM', actual: $response['body']['clientCode']); + $this->assertEquals('Chrome Mobile', $response['body']['clientName']); + + // Forwarded User Agent without API Key + $response = $this->client->call(Client::METHOD_POST, '/users/' . $data['id'] . '/tokens', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'expire' => 60 + ]); + + $userId = $response['body']['userId']; + $secret = $response['body']['secret']; + + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/token', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-forwarded-user-agent' => 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36' + ], [ + 'userId' => $userId, + 'secret' => $secret + ]); + + $this->assertEquals('browser', $response['body']['clientType']); + $this->assertEquals('CH', $response['body']['clientCode']); + $this->assertEquals('Chrome', $response['body']['clientName']); /** * Test for FAILURE @@ -2364,6 +2419,33 @@ class AccountCustomClientTest extends Scope $message = $smsRequest['data']['message']; $token = substr($message, 0, 6); + /** + * Test for FAILURE + */ + + // disable phone sessions + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $this->getProject()['$id'] . '/auth/phone', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ]), [ + 'status' => false, + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(false, $response['body']['authPhone']); + + $response = $this->client->call(Client::METHOD_POST, '/account/verification/phone', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ])); + + $this->assertEquals(501, $response['headers']['status-code']); + $this->assertEquals("Phone authentication is disabled for this project", $response['body']['message']); + return \array_merge($data, [ 'token' => \substr($smsRequest['data']['message'], 0, 6) ]); diff --git a/tests/e2e/Services/Console/ConsoleConsoleClientTest.php b/tests/e2e/Services/Console/ConsoleConsoleClientTest.php index ca9287cdca..6059cb2000 100644 --- a/tests/e2e/Services/Console/ConsoleConsoleClientTest.php +++ b/tests/e2e/Services/Console/ConsoleConsoleClientTest.php @@ -24,13 +24,19 @@ class ConsoleConsoleClientTest extends Scope ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertCount(7, $response['body']); - $this->assertIsString($response['body']['_APP_DOMAIN_TARGET']); + $this->assertCount(13, $response['body']); + $this->assertIsString($response['body']['_APP_DOMAIN_TARGET_CNAME']); + $this->assertIsString($response['body']['_APP_DOMAIN_TARGET_A']); + $this->assertIsString($response['body']['_APP_DOMAIN_TARGET_AAAA']); $this->assertIsInt($response['body']['_APP_STORAGE_LIMIT']); - $this->assertIsInt($response['body']['_APP_FUNCTIONS_SIZE_LIMIT']); - $this->assertIsString($response['body']['_APP_DOMAIN_TARGET']); + $this->assertIsInt($response['body']['_APP_COMPUTE_SIZE_LIMIT']); $this->assertIsBool($response['body']['_APP_DOMAIN_ENABLED']); $this->assertIsBool($response['body']['_APP_VCS_ENABLED']); $this->assertIsBool($response['body']['_APP_ASSISTANT_ENABLED']); + $this->assertIsString($response['body']['_APP_DOMAIN_SITES']); + $this->assertIsString($response['body']['_APP_DOMAIN_FUNCTIONS']); + $this->assertIsString($response['body']['_APP_OPTIONS_FORCE_HTTPS']); + $this->assertIsString($response['body']['_APP_DOMAINS_NAMESERVERS']); + // When adding new keys, dont forget to update count a few lines above } } diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index d079cb313c..0f57f94515 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -399,6 +399,73 @@ trait DatabasesBase $this->assertEquals(400, $response['headers']['status-code']); } + /** + * @depends testCreateDatabase + */ + public function testPatchAttribute(array $data): void + { + $databaseId = $data['databaseId']; + + $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' => 'patch', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + ], + ]); + + $this->assertEquals(201, $collection['headers']['status-code']); + $this->assertEquals($collection['body']['name'], 'patch'); + + $attribute = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection['body']['$id'].'/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'required' => true, + 'size' => 100, + ]); + $this->assertEquals(202, $attribute['headers']['status-code']); + $this->assertEquals($attribute['body']['size'], 100); + + sleep(1); + + $index = $this->client->call(Client::METHOD_POST, '/databases/'.$databaseId.'/collections/'.$collection['body']['$id'].'/indexes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'titleIndex', + 'type' => 'key', + 'attributes' => ['title'], + ]); + $this->assertEquals(202, $index['headers']['status-code']); + + sleep(1); + + /** + * Update attribute size to exceed Index maximum length + */ + $attribute = $this->client->call(Client::METHOD_PATCH, '/databases/'.$databaseId.'/collections/'.$collection['body']['$id'].'/attributes/string/'.$attribute['body']['key'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'size' => 1000, + 'required' => true, + 'default' => null, + ]); + + $this->assertEquals(400, $attribute['headers']['status-code']); + $this->assertStringContainsString('Index length is longer than the maximum: 76', $attribute['body']['message']); + } + public function testUpdateAttributeEnum(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', [ @@ -1300,7 +1367,7 @@ trait DatabasesBase ]); $this->assertEquals(400, $unknown['headers']['status-code']); - $this->assertEquals('Unknown attribute: Unknown', $unknown['body']['message']); + $this->assertEquals('Unknown attribute: Unknown. Verify the attribute name or create the attribute.', $unknown['body']['message']); $index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/indexes', array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php index 96bb0b5609..2266c91afe 100644 --- a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php @@ -224,7 +224,7 @@ class DatabasesConsoleClientTest extends Scope ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(7, count($response['body'])); + $this->assertEquals(11, count($response['body'])); $this->assertEquals('24h', $response['body']['range']); $this->assertIsNumeric($response['body']['documentsTotal']); $this->assertIsNumeric($response['body']['collectionsTotal']); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 7cb8adb815..57e0b93634 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -1362,7 +1362,7 @@ class DatabasesCustomServerTest extends Scope ]); $this->assertEquals(400, $tooWide['headers']['status-code']); - $this->assertEquals('Attribute limit exceeded', $tooWide['body']['message']); + $this->assertEquals('attribute_limit_exceeded', $tooWide['body']['type']); } public function testIndexLimitException() @@ -2309,6 +2309,30 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(100, $new['body']['min']); $this->assertEquals(2000, $new['body']['max']); + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 100, + 'min' => 0, + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 10, + 'max' => 100, + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + /** * Test against failure */ @@ -2368,32 +2392,6 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), [ - 'required' => false, - 'default' => 100, - 'min' => 0, - ]); - - $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), [ - 'required' => false, - 'default' => 100, - 'max' => 0, - ]); - - $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -2572,6 +2570,30 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(123.456, $new['body']['min']); $this->assertEquals(2000, $new['body']['max']); + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 123.456, + 'min' => 0.0, + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + + $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'required' => false, + 'default' => 23.456, + 'max' => 100.0, + ]); + + $this->assertEquals(200, $update['headers']['status-code']); + /** * Test against failure */ @@ -2631,32 +2653,6 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(400, $update['headers']['status-code']); $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), [ - 'required' => false, - 'default' => 123.456, - 'min' => 0.0, - ]); - - $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), [ - 'required' => false, - 'default' => 123.456, - 'max' => 0.0, - ]); - - $this->assertEquals(400, $update['headers']['status-code']); - $this->assertEquals(AppwriteException::GENERAL_ARGUMENT_INVALID, $update['body']['type']); - $update = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/float/' . $key, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], diff --git a/tests/e2e/Services/Functions/FunctionsBase.php b/tests/e2e/Services/Functions/FunctionsBase.php index a1bb8f2b21..475eb9b9b4 100644 --- a/tests/e2e/Services/Functions/FunctionsBase.php +++ b/tests/e2e/Services/Functions/FunctionsBase.php @@ -6,6 +6,9 @@ use Appwrite\Tests\Async; use CURLFile; use Tests\E2E\Client; use Utopia\CLI\Console; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Query; +use Utopia\System\System; trait FunctionsBase { @@ -48,6 +51,18 @@ trait FunctionsBase $this->assertEquals('ready', $deployment['body']['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); }, 50000, 500); + // Not === so multipart/form-data works fine too + if (($params['activate'] ?? false) == true) { + $this->assertEventually(function () use ($functionId, $deploymentId) { + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertEquals($deploymentId, $function['body']['deploymentId'], 'Deployment is not activated, deployment: ' . json_encode($function['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + } + return $deploymentId; } @@ -72,6 +87,16 @@ trait FunctionsBase return $function; } + protected function updateFunction(string $functionId, mixed $params): mixed + { + $function = $this->client->call(Client::METHOD_PUT, '/functions/' . $functionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $function; + } + protected function createVariable(string $functionId, mixed $params): mixed { $variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([ @@ -82,6 +107,46 @@ trait FunctionsBase return $variable; } + protected function getVariable(string $functionId, string $variableId): mixed + { + $variable = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/variables/' . $variableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $variable; + } + + protected function updateVariable(string $functionId, string $variableId, mixed $params): mixed + { + $variable = $this->client->call(Client::METHOD_PUT, '/functions/' . $functionId . '/variables/' . $variableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $variable; + } + + protected function listVariables(string $functionId, mixed $params = []): mixed + { + $variables = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/variables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $variables; + } + + protected function deleteVariable(string $functionId, string $variableId): mixed + { + $variable = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId . '/variables/' . $variableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $variable; + } + protected function getFunction(string $functionId): mixed { $function = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId, array_merge([ @@ -166,7 +231,27 @@ trait FunctionsBase return $deployment; } - protected function getFunctionUsage(string $functionId, mixed $params): mixed + protected function deleteDeployment(string $functionId, string $deploymentId): mixed + { + $deployment = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId . '/deployments/' . $deploymentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + return $deployment; + } + + protected function createTemplateDeployment(string $functionId, mixed $params = []): mixed + { + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments/template', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $deployment; + } + + protected function getUsage(string $functionId, mixed $params): mixed { $usage = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/usage', array_merge([ 'content-type' => 'application/json', @@ -181,7 +266,7 @@ trait FunctionsBase $template = $this->client->call(Client::METHOD_GET, '/functions/templates/' . $templateId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ])); return $template; } @@ -205,4 +290,123 @@ trait FunctionsBase return $function; } + + protected function setupFunctionDomain(string $functionId, string $subdomain = ''): string + { + $subdomain = $subdomain ? $subdomain : ID::unique(); + $rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/function', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'domain' => $subdomain . '.' . System::getEnv('_APP_DOMAIN_FUNCTIONS', ''), + 'functionId' => $functionId, + ]); + + $this->assertEquals(201, $rule['headers']['status-code']); + $this->assertNotEmpty($rule['body']['$id']); + $this->assertNotEmpty($rule['body']['domain']); + + $domain = $rule['body']['domain']; + + return $domain; + } + + protected function getFunctionDomain(string $functionId): string + { + $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('deploymentResourceId', [$functionId])->toString(), + Query::equal('trigger', ['manual'])->toString(), + Query::equal('type', ['deployment'])->toString(), + ], + ]); + + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertGreaterThanOrEqual(1, $rules['body']['total']); + $this->assertGreaterThanOrEqual(1, \count($rules['body']['rules'])); + $this->assertNotEmpty($rules['body']['rules'][0]['domain']); + + $domain = $rules['body']['rules'][0]['domain']; + + return $domain; + } + + protected function getDeploymentDownload(string $functionId, string $deploymentId, string $type): mixed + { + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/deployments/' . $deploymentId . '/download', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'type' => $type + ]); + + return $response; + } + + protected function setupDuplicateDeployment(string $functionId, string $deploymentId): string + { + $deployment = $this->createDuplicateDeployment($functionId, $deploymentId); + $this->assertEquals(202, $deployment['headers']['status-code']); + + $deploymentId = $deployment['body']['$id']; + $this->assertNotEmpty($deploymentId); + + $this->assertEventually(function () use ($functionId, $deploymentId) { + $deployment = $this->getDeployment($functionId, $deploymentId); + $this->assertEquals('ready', $deployment['body']['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + $this->assertEventually(function () use ($functionId, $deploymentId) { + $function = $this->getFunction($functionId); + $this->assertEquals($deploymentId, $function['body']['deploymentId'], 'Deployment is not activated, deployment: ' . json_encode($function['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + return $deploymentId; + } + + protected function createDuplicateDeployment(string $functionId, string $deploymentId): mixed + { + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments/duplicate', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'deploymentId' => $deploymentId, + ]); + + return $deployment; + } + + protected function updateFunctionDeployment(string $functionId, string $deploymentId): mixed + { + $function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployment', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'deploymentId' => $deploymentId + ]); + + return $function; + } + + protected function cancelDeployment(string $functionId, string $deploymentId): mixed + { + $deployment = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId . '/status', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $deployment; + } + + protected function listSpecifications(): mixed + { + $specifications = $this->client->call(Client::METHOD_GET, '/functions/specifications', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $specifications; + } } diff --git a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php index 0708d40aab..24215f5352 100644 --- a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php @@ -58,11 +58,11 @@ class FunctionsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $usage = $this->getFunctionUsage($data['functionId'], [ + $usage = $this->getUsage($data['functionId'], [ 'range' => '24h' ]); $this->assertEquals(200, $usage['headers']['status-code']); - $this->assertEquals(19, count($usage['body'])); + $this->assertEquals(24, count($usage['body'])); $this->assertEquals('24h', $usage['body']['range']); $this->assertIsNumeric($usage['body']['deploymentsTotal']); $this->assertIsNumeric($usage['body']['deploymentsStorageTotal']); @@ -87,12 +87,12 @@ class FunctionsConsoleClientTest extends Scope /** * Test for FAILURE */ - $usage = $this->getFunctionUsage($data['functionId'], [ + $usage = $this->getUsage($data['functionId'], [ 'range' => '232h' ]); $this->assertEquals(400, $usage['headers']['status-code']); - $usage = $this->getFunctionUsage('randomFunctionId', [ + $usage = $this->getUsage('randomFunctionId', [ 'range' => '24h' ]); $this->assertEquals(404, $usage['headers']['status-code']); @@ -110,7 +110,8 @@ class FunctionsConsoleClientTest extends Scope $data['functionId'], [ 'key' => 'APP_TEST', - 'value' => 'TESTINGVALUE' + 'value' => 'TESTINGVALUE', + 'secret' => false ] ); @@ -131,6 +132,7 @@ class FunctionsConsoleClientTest extends Scope $this->assertEquals(201, $variable['headers']['status-code']); $this->assertEquals('APP_TEST_1', $variable['body']['key']); $this->assertEmpty($variable['body']['value']); + $this->assertTrue($variable['body']['secret']); $secretVariableId = $variable['body']['$id']; @@ -142,7 +144,8 @@ class FunctionsConsoleClientTest extends Scope $data['functionId'], [ 'key' => 'APP_TEST', - 'value' => 'ANOTHERTESTINGVALUE' + 'value' => 'ANOTHERTESTINGVALUE', + 'secret' => false ] ); @@ -320,6 +323,41 @@ class FunctionsConsoleClientTest extends Scope $this->assertEquals("APP_TEST_UPDATE_2", $variable['body']['key']); $this->assertEquals("TESTINGVALUEUPDATED", $variable['body']['value']); + // convert non-secret variable to secret + $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'key' => 'APP_TEST_UPDATE_2', + 'secret' => true + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals("APP_TEST_UPDATE_2", $response['body']['key']); + $this->assertEmpty($response['body']['value']); + $this->assertTrue($response['body']['secret']); + + $variable = $this->client->call(Client::METHOD_GET, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $variable['headers']['status-code']); + $this->assertEquals("APP_TEST_UPDATE_2", $variable['body']['key']); + $this->assertEmpty($variable['body']['value']); + $this->assertTrue($variable['body']['secret']); + + // convert secret variable to non-secret + $response = $this->client->call(Client::METHOD_PUT, '/functions/' . $data['functionId'] . '/variables/' . $data['variableId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'key' => 'APP_TEST_UPDATE', + 'secret' => false + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + /** * Test for FAILURE */ @@ -410,4 +448,93 @@ class FunctionsConsoleClientTest extends Scope return $data; } + + public function testVariableE2E(): void + { + $function = $this->createFunction([ + 'functionId' => ID::unique(), + 'runtime' => 'node-18.0', + 'name' => 'Variable E2E Test', + 'entrypoint' => 'index.js', + 'logging' => false, + 'execute' => ['any'] + ]); + + $this->assertEquals(201, $function['headers']['status-code']); + $this->assertFalse($function['body']['logging']); + $this->assertNotEmpty($function['body']['$id']); + + $functionId = $function['body']['$id'] ?? ''; + + // create variable + $variable = $this->createVariable($functionId, [ + 'key' => 'CUSTOM_VARIABLE', + 'value' => 'a_secret_value', + 'secret' => true, + ]); + + $this->assertEquals(201, $variable['headers']['status-code']); + $this->assertNotEmpty($variable['body']['$id']); + $this->assertEquals('CUSTOM_VARIABLE', $variable['body']['key']); + $this->assertEquals('', $variable['body']['value']); + $this->assertEquals(true, $variable['body']['secret']); + + $deploymentId = $this->setupDeployment($functionId, [ + 'entrypoint' => 'index.js', + 'code' => $this->packageFunction('node'), + 'activate' => true + ]); + + $this->assertNotEmpty($deploymentId); + + $execution = $this->createExecution($functionId); + + $this->assertEquals(201, $execution['headers']['status-code']); + $this->assertEmpty($execution['body']['logs']); + $this->assertEmpty($execution['body']['errors']); + $body = json_decode($execution['body']['responseBody']); + $this->assertEquals('a_secret_value', $body->CUSTOM_VARIABLE); + + $this->cleanupFunction($functionId); + } + + public function testFunctionDownload(): void + { + $functionId = $this->setupFunction([ + 'functionId' => ID::unique(), + 'runtime' => 'node-18.0', + 'name' => 'Download Test', + 'entrypoint' => 'index.js', + 'logging' => false, + 'execute' => ['any'] + ]); + + $deploymentId = $this->setupDeployment($functionId, [ + 'entrypoint' => 'index.js', + 'code' => $this->packageFunction('node'), + 'activate' => true + ]); + + $this->assertNotEmpty($deploymentId); + + $response = $this->getDeploymentDownload($functionId, $deploymentId, 'source'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('application/gzip', $response['headers']['content-type']); + $this->assertGreaterThan(0, $response['headers']['content-length']); + $this->assertGreaterThan(0, \strlen($response['body'])); + + $deploymentMd5 = \md5($response['body']); + + $response = $this->getDeploymentDownload($functionId, $deploymentId, 'output'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('application/gzip', $response['headers']['content-type']); + $this->assertGreaterThan(0, $response['headers']['content-length']); + $this->assertGreaterThan(0, \strlen($response['body'])); + + $buildMd5 = \md5($response['body']); + + $this->assertNotEquals($deploymentMd5, $buildMd5); + + $this->cleanupFunction($functionId); + } } diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 914a255663..a47bc62d47 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -8,6 +8,7 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; +use Utopia\System\System; class FunctionsCustomClientTest extends Scope { @@ -74,8 +75,6 @@ class FunctionsCustomClientTest extends Scope $this->cleanupFunction($functionId); } - - public function testCreateCustomExecution(): array { /** @@ -111,7 +110,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals('PHP', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); $this->assertEquals('8.0', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']); $this->assertEquals(APP_VERSION_STABLE, $output['APPWRITE_VERSION']); - $this->assertEquals('default', $output['APPWRITE_REGION']); + $this->assertEquals(System::getEnv('_APP_REGION', 'default'), $output['APPWRITE_REGION']); $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']); $this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']); $this->assertEquals($this->getUser()['$id'], $output['APPWRITE_FUNCTION_USER_ID']); @@ -221,7 +220,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals('PHP', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); $this->assertEquals('8.0', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']); $this->assertEquals(APP_VERSION_STABLE, $output['APPWRITE_VERSION']); - $this->assertEquals('default', $output['APPWRITE_REGION']); + $this->assertEquals(System::getEnv('_APP_REGION', 'default'), $output['APPWRITE_REGION']); $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']); $this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']); $this->assertEquals($this->getUser()['$id'], $output['APPWRITE_FUNCTION_USER_ID']); @@ -277,6 +276,7 @@ class FunctionsCustomClientTest extends Scope // List all templates $templates = $this->client->call(Client::METHOD_GET, '/functions/templates', array_merge([ 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(200, $templates['headers']['status-code']); @@ -297,17 +297,19 @@ class FunctionsCustomClientTest extends Scope // List templates with pagination $templatesOffset = $this->client->call(Client::METHOD_GET, '/functions/templates', array_merge([ 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'limit' => 1, 'offset' => 2 ]); $this->assertEquals(200, $templatesOffset['headers']['status-code']); - $this->assertEquals(1, $templatesOffset['body']['total']); + $this->addToAssertionCount(1, $templatesOffset['body']['templates']); $this->assertEquals($templates['body']['templates'][2]['id'], $templatesOffset['body']['templates'][0]['id']); // List templates with filters $templates = $this->client->call(Client::METHOD_GET, '/functions/templates', array_merge([ 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'useCases' => ['starter', 'ai'], 'runtimes' => ['bun-1.0', 'dart-2.16'] @@ -319,7 +321,16 @@ class FunctionsCustomClientTest extends Scope $this->assertContains($template['useCases'][0], ['starter', 'ai']); } $this->assertArrayHasKey('runtimes', $templates['body']['templates'][0]); - $this->assertContains('bun-1.0', array_column($templates['body']['templates'][0]['runtimes'], 'name')); + + foreach ($templates['body']['templates'] as $template) { + $this->assertThat( + \array_column($template['runtimes'], 'name'), + $this->logicalOr( + $this->containsEqual('bun-1.0'), + $this->containsEqual('dart-2.16'), + ), + ); + } // List templates with pagination and filters $templates = $this->client->call(Client::METHOD_GET, '/functions/templates', array_merge([ @@ -333,7 +344,7 @@ class FunctionsCustomClientTest extends Scope ]); $this->assertEquals(200, $templates['headers']['status-code']); - $this->assertEquals(5, $templates['body']['total']); + $this->assertCount(5, $templates['body']['templates']); $this->assertIsArray($templates['body']['templates']); $this->assertArrayHasKey('runtimes', $templates['body']['templates'][0]); @@ -349,6 +360,7 @@ class FunctionsCustomClientTest extends Scope // List templates with invalid limit $templates = $this->client->call(Client::METHOD_GET, '/functions/templates', array_merge([ 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'limit' => 5001, 'offset' => 10, diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 9b9f03a100..e3ef8f0fc8 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -2,7 +2,8 @@ namespace Tests\E2E\Services\Functions; -use Appwrite\Functions\Specification; +use Appwrite\Platform\Modules\Compute\Specification; +use Appwrite\Tests\Retry; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; @@ -13,7 +14,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; -use Utopia\System\System; class FunctionsCustomServerTest extends Scope { @@ -21,6 +21,41 @@ class FunctionsCustomServerTest extends Scope use ProjectCustom; use SideServer; + public function testListSpecs(): void + { + $specifications = $this->listSpecifications(); + $this->assertEquals(200, $specifications['headers']['status-code']); + $this->assertGreaterThan(0, $specifications['body']['total']); + $this->assertArrayHasKey(0, $specifications['body']['specifications']); + $this->assertArrayHasKey('memory', $specifications['body']['specifications'][0]); + $this->assertArrayHasKey('cpus', $specifications['body']['specifications'][0]); + $this->assertArrayHasKey('enabled', $specifications['body']['specifications'][0]); + $this->assertArrayHasKey('slug', $specifications['body']['specifications'][0]); + + $function = $this->createFunction([ + 'functionId' => ID::unique(), + 'name' => 'Specs function', + 'runtime' => 'php-8.0', + 'specification' => $specifications['body']['specifications'][0]['slug'] + ]); + $this->assertEquals(201, $function['headers']['status-code']); + $this->assertEquals($specifications['body']['specifications'][0]['slug'], $function['body']['specification']); + + $function = $this->getFunction($function['body']['$id']); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertEquals($specifications['body']['specifications'][0]['slug'], $function['body']['specification']); + + $this->cleanupFunction($function['body']['$id']); + + $function = $this->createFunction([ + 'functionId' => ID::unique(), + 'name' => 'Specs function', + 'runtime' => 'php-8.0', + 'specification' => 'cheap-please' + ]); + $this->assertEquals(400, $function['headers']['status-code']); + } + public function testCreateFunction(): array { /** @@ -38,7 +73,7 @@ class FunctionsCustomServerTest extends Scope 'timeout' => 10, ]); - $functionId = $functionId = $function['body']['$id'] ?? ''; + $functionId = $function['body']['$id'] ?? ''; $dateValidator = new DatetimeValidator(); $this->assertEquals(201, $function['headers']['status-code']); @@ -47,7 +82,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals('php-8.0', $function['body']['runtime']); $this->assertEquals(true, $dateValidator->isValid($function['body']['$createdAt'])); $this->assertEquals(true, $dateValidator->isValid($function['body']['$updatedAt'])); - $this->assertEquals('', $function['body']['deployment']); + $this->assertEquals('', $function['body']['deploymentId']); $this->assertEquals([ 'buckets.*.create', 'buckets.*.delete', @@ -262,7 +297,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals('Test1', $function['body']['name']); $this->assertEquals(true, $dateValidator->isValid($function['body']['$createdAt'])); $this->assertEquals(true, $dateValidator->isValid($function['body']['$updatedAt'])); - $this->assertEquals('', $function['body']['deployment']); + $this->assertEquals('', $function['body']['deploymentId']); $this->assertEquals([ 'users.*.update.name', 'users.*.update.email', @@ -356,7 +391,28 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $function['headers']['status-code']); $this->assertNotEmpty($function['body']['$id']); - $functionId = $functionId = $function['body']['$id'] ?? ''; + $functionId = $function['body']['$id'] ?? ''; + + $deployment = $this->createTemplateDeployment( + $functionId, + [ + 'functionId' => ID::unique(), + 'activate' => true, + 'repository' => $starterTemplate['body']['providerRepositoryId'], + 'owner' => $starterTemplate['body']['providerOwner'], + 'rootDirectory' => $phpRuntime['providerRootDirectory'], + 'version' => $starterTemplate['body']['providerVersion'], + ] + ); + + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + + $deployment = $this->getDeployment($functionId, $deployment['body']['$id']); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertEquals(0, $deployment['body']['sourceSize']); + $this->assertEquals(0, $deployment['body']['buildSize']); + $this->assertEquals(0, $deployment['body']['totalSize']); $deployments = $this->listDeployments($functionId); @@ -366,7 +422,7 @@ class FunctionsCustomServerTest extends Scope $lastDeployment = $deployments['body']['deployments'][0]; $this->assertNotEmpty($lastDeployment['$id']); - $this->assertEquals(0, $lastDeployment['size']); + $this->assertEquals(0, $lastDeployment['sourceSize']); $deploymentId = $lastDeployment['$id']; @@ -375,12 +431,12 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $deployment['headers']['status-code']); $this->assertEquals('ready', $deployment['body']['status']); - }, 500000, 1000); + }, 50000, 1000); $function = $this->getFunction($functionId); $this->assertEquals(200, $function['headers']['status-code']); - $this->assertEquals($deploymentId, $function['body']['deployment']); + $this->assertEquals($deploymentId, $function['body']['deploymentId']); // Test starter code is used and that dynamic keys work $execution = $this->createExecution($functionId, [ @@ -430,7 +486,21 @@ class FunctionsCustomServerTest extends Scope $this->assertStringContainsString("Total users: " . $totalUsers, $execution['body']['logs']); }, 10000, 500); - $function = $this->deleteFunction($functionId); + $deployment = $this->getDeployment($functionId, $deployment['body']['$id']); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertGreaterThan(0, $deployment['body']['sourceSize']); + $this->assertGreaterThan(0, $deployment['body']['buildSize']); + $totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize']; + $this->assertEquals($totalSize, $deployment['body']['totalSize']); + + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertNotEmpty($function['body']['deploymentId']); + $this->assertNotEmpty($function['body']['deploymentCreatedAt']); + $this->assertEquals($deployment['body']['$id'], $function['body']['deploymentId']); + $this->assertEquals($deployment['body']['$createdAt'], $function['body']['deploymentCreatedAt']); + + $function = $this->cleanupFunction($functionId); } /** @@ -450,6 +520,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(202, $deployment['headers']['status-code']); $this->assertNotEmpty($deployment['body']['$id']); + $this->assertEquals('waiting', $deployment['body']['status']); $this->assertEquals(true, (new DatetimeValidator())->isValid($deployment['body']['$createdAt'])); $this->assertEquals('index.php', $deployment['body']['entrypoint']); @@ -480,8 +551,8 @@ class FunctionsCustomServerTest extends Scope $function = $this->getFunction($functionId); $this->assertEquals(200, $function['headers']['status-code']); - $this->assertEquals($deploymentIdActive, $function['body']['deployment']); - $this->assertNotEquals($deploymentIdInactive, $function['body']['deployment']); + $this->assertEquals($deploymentIdActive, $function['body']['deploymentId']); + $this->assertNotEquals($deploymentIdInactive, $function['body']['deploymentId']); $deployment = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId . '/deployments/' . $deploymentIdInactive, array_merge([ 'content-type' => 'application/json', @@ -496,6 +567,7 @@ class FunctionsCustomServerTest extends Scope /** * @depends testUpdateFunction */ + #[Retry(count: 3)] public function testCancelDeploymentBuild($data): void { $functionId = $data['functionId']; @@ -519,14 +591,9 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals('building', $deployment['body']['status']); }, 100000, 250); - // Cancel the deployment - $cancel = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId . '/build', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - - $this->assertEquals(200, $cancel['headers']['status-code']); - $this->assertEquals('canceled', $cancel['body']['status']); + $deployment = $this->cancelDeployment($functionId, $deploymentId); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertEquals('canceled', $deployment['body']['status']); /** * Build worker still runs the build. @@ -586,10 +653,10 @@ class FunctionsCustomServerTest extends Scope $this->assertNotEmpty($largeTag['body']['$id']); $this->assertEquals(true, (new DatetimeValidator())->isValid($largeTag['body']['$createdAt'])); $this->assertEquals('index.php', $largeTag['body']['entrypoint']); - $this->assertGreaterThan(1024 * 1024 * 5, $largeTag['body']['size']); // ~7MB video file - $this->assertLessThan(1024 * 1024 * 10, $largeTag['body']['size']); // ~7MB video file + $this->assertGreaterThan(1024 * 1024 * 5, $largeTag['body']['sourceSize']); // ~7MB video file + $this->assertLessThan(1024 * 1024 * 10, $largeTag['body']['sourceSize']); // ~7MB video file - $deploymentSize = $largeTag['body']['size']; + $deploymentSize = $largeTag['body']['sourceSize']; $deploymentId = $largeTag['body']['$id']; $this->assertEventually(function () use ($functionId, $deploymentId, $deploymentSize) { @@ -597,7 +664,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $deployment['headers']['status-code']); $this->assertEquals('ready', $deployment['body']['status']); - $this->assertEquals($deploymentSize, $deployment['body']['size']); + $this->assertEquals($deploymentSize, $deployment['body']['sourceSize']); $this->assertGreaterThan(1024 * 1024 * 10, $deployment['body']['buildSize']); // ~7MB video file + 10MB sample file }, 500000, 1000); @@ -623,7 +690,7 @@ class FunctionsCustomServerTest extends Scope $this->assertNotEmpty($response['body']['$id']); $this->assertEquals(true, $dateValidator->isValid($response['body']['$createdAt'])); $this->assertEquals(true, $dateValidator->isValid($response['body']['$updatedAt'])); - $this->assertEquals($data['deploymentId'], $response['body']['deployment']); + $this->assertEquals($data['deploymentId'], $response['body']['deploymentId']); return $data; } @@ -643,7 +710,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($deployments['body']['total'], 3); $this->assertIsArray($deployments['body']['deployments']); $this->assertCount(3, $deployments['body']['deployments']); - $this->assertArrayHasKey('size', $deployments['body']['deployments'][0]); + $this->assertArrayHasKey('sourceSize', $deployments['body']['deployments'][0]); $this->assertArrayHasKey('buildSize', $deployments['body']['deployments'][0]); $deployments = $this->listDeployments($functionId, [ @@ -664,24 +731,6 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($deployments['headers']['status-code'], 200); $this->assertCount(2, $deployments['body']['deployments']); - $deployments = $this->listDeployments($functionId, [ - 'queries' => [ - Query::equal('entrypoint', ['index.php'])->toString(), - ], - ]); - - $this->assertEquals($deployments['headers']['status-code'], 200); - $this->assertCount(3, $deployments['body']['deployments']); - - $deployments = $this->listDeployments($functionId, [ - 'queries' => [ - Query::equal('entrypoint', ['index.js'])->toString(), - ], - ]); - - $this->assertEquals($deployments['headers']['status-code'], 200); - $this->assertCount(0, $deployments['body']['deployments']); - $deployments = $this->listDeployments($functionId, [ 'search' => 'php-8.0' ]); @@ -732,7 +781,7 @@ class FunctionsCustomServerTest extends Scope $functionId, [ 'queries' => [ - Query::greaterThan('size', 10000)->toString(), + Query::greaterThan('sourceSize', 10000)->toString(), ], ] ); @@ -744,7 +793,7 @@ class FunctionsCustomServerTest extends Scope $functionId, [ 'queries' => [ - Query::greaterThan('size', 0)->toString(), + Query::greaterThan('sourceSize', 0)->toString(), ], ] ); @@ -756,7 +805,7 @@ class FunctionsCustomServerTest extends Scope $functionId, [ 'queries' => [ - Query::greaterThan('size', -100)->toString(), + Query::greaterThan('sourceSize', -100)->toString(), ], ] ); @@ -777,16 +826,16 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $deployments['headers']['status-code']); $this->assertGreaterThanOrEqual(1, $deployments['body']['total']); $this->assertNotEmpty($deployments['body']['deployments'][0]['$id']); - $this->assertNotEmpty($deployments['body']['deployments'][0]['size']); + $this->assertNotEmpty($deployments['body']['deployments'][0]['sourceSize']); $deploymentId = $deployments['body']['deployments'][0]['$id']; - $deploymentSize = $deployments['body']['deployments'][0]['size']; + $deploymentSize = $deployments['body']['deployments'][0]['sourceSize']; $deployments = $this->listDeployments( $functionId, [ 'queries' => [ - Query::equal('size', [$deploymentSize])->toString(), + Query::equal('sourceSize', [$deploymentSize])->toString(), ], ] ); @@ -803,7 +852,7 @@ class FunctionsCustomServerTest extends Scope if (!empty($matchingDeployment)) { $deployment = reset($matchingDeployment); - $this->assertEquals($deploymentSize, $deployment['size']); + $this->assertEquals($deploymentSize, $deployment['sourceSize']); } return $data; @@ -820,10 +869,10 @@ class FunctionsCustomServerTest extends Scope $deployment = $this->getDeployment($data['functionId'], $data['deploymentId']); $this->assertEquals(200, $deployment['headers']['status-code']); - $this->assertGreaterThan(0, $deployment['body']['buildTime']); + $this->assertGreaterThan(0, $deployment['body']['buildDuration']); $this->assertNotEmpty($deployment['body']['status']); $this->assertNotEmpty($deployment['body']['buildLogs']); - $this->assertArrayHasKey('size', $deployment['body']); + $this->assertArrayHasKey('sourceSize', $deployment['body']); $this->assertArrayHasKey('buildSize', $deployment['body']); /** @@ -1241,7 +1290,7 @@ class FunctionsCustomServerTest extends Scope ['folder' => 'node', 'name' => 'node-18.0', 'entrypoint' => 'index.js', 'runtimeName' => 'Node.js', 'runtimeVersion' => '18.0'], ['folder' => 'python', 'name' => 'python-3.9', 'entrypoint' => 'main.py', 'runtimeName' => 'Python', 'runtimeVersion' => '3.9'], ['folder' => 'ruby', 'name' => 'ruby-3.1', 'entrypoint' => 'main.rb', 'runtimeName' => 'Ruby', 'runtimeVersion' => '3.1'], - // Swift and Dart disabled as it's very slow. + // Swift and Dart disabled on purpose, as it's very slow. // [ 'folder' => 'dart', 'name' => 'dart-2.15', 'entrypoint' => 'main.dart', 'runtimeName' => 'Dart', 'runtimeVersion' => '2.15' ], // [ 'folder' => 'swift', 'name' => 'swift-5.5', 'entrypoint' => 'index.swift', 'runtimeName' => 'Swift', 'runtimeVersion' => '5.5' ], ]; @@ -1465,7 +1514,7 @@ class FunctionsCustomServerTest extends Scope $runtimes = $this->client->call(Client::METHOD_GET, '/functions/runtimes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ])); $this->assertEquals(200, $runtimes['headers']['status-code']); $this->assertGreaterThan(0, $runtimes['body']['total']); @@ -1541,7 +1590,7 @@ class FunctionsCustomServerTest extends Scope $functionId = $this->setupFunction([ 'functionId' => ID::unique(), 'name' => 'Test PHP Scopes executions', - 'commands' => 'sh setup.sh && composer install', + 'commands' => 'bash setup.sh && composer install', 'runtime' => 'php-8.0', 'entrypoint' => 'index.php', 'scopes' => ['users.read'], @@ -1604,11 +1653,14 @@ class FunctionsCustomServerTest extends Scope 'entrypoint' => 'index.php', 'timeout' => 15, ]); - $this->setupDeployment($functionId, [ + $this->assertNotEmpty($functionId); + + $deploymentId = $this->setupDeployment($functionId, [ 'entrypoint' => 'index.php', 'code' => $this->packageFunction('php-cookie'), 'activate' => true ]); + $this->assertNotEmpty($deploymentId); $cookie = 'cookieName=cookieValue; cookie2=value2; cookie3=value=3; cookie4=val:ue4; cookie5=value5'; $execution = $this->createExecution($functionId, [ @@ -1624,6 +1676,13 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($cookie, $execution['body']['responseBody']); $this->assertGreaterThan(0, $execution['body']['duration']); + $deployment = $this->getDeployment($functionId, $deploymentId); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertGreaterThan(0, $deployment['body']['sourceSize']); + $this->assertGreaterThan(0, $deployment['body']['buildSize']); + $totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize']; + $this->assertEquals($totalSize, $deployment['body']['totalSize']); + $this->cleanupFunction($functionId); } @@ -1638,22 +1697,7 @@ class FunctionsCustomServerTest extends Scope 'execute' => ['any'] ]); - $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => [ - Query::equal('resourceId', [$functionId])->toString(), - Query::equal('resourceType', ['function'])->toString(), - ], - ]); - - $this->assertEquals(200, $rules['headers']['status-code']); - $this->assertEquals(1, $rules['body']['total']); - $this->assertCount(1, $rules['body']['rules']); - $this->assertNotEmpty($rules['body']['rules'][0]['domain']); - - $domain = $rules['body']['rules'][0]['domain']; + $domain = $this->setupFunctionDomain($functionId); $this->setupDeployment($functionId, [ 'entrypoint' => 'index.php', @@ -1686,16 +1730,13 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(1, count($executions['body']['executions'])); }); - // Await Aggregation - sleep(System::getEnv('_APP_USAGE_AGGREGATION_INTERVAL', 30)); - $this->assertEventually(function () use ($functionId) { - $response = $this->getFunctionUsage($functionId, [ + $response = $this->getUsage($functionId, [ 'range' => '24h' ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(19, count($response['body'])); + $this->assertEquals(24, count($response['body'])); $this->assertEquals('24h', $response['body']['range']); $this->assertEquals(1, $response['body']['executionsTotal']); }, 25000, 1000); @@ -1714,22 +1755,7 @@ class FunctionsCustomServerTest extends Scope 'execute' => ['any'] ]); - $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => [ - Query::equal('resourceId', [$functionId])->toString(), - Query::equal('resourceType', ['function'])->toString(), - ], - ]); - - $this->assertEquals(200, $rules['headers']['status-code']); - $this->assertEquals(1, $rules['body']['total']); - $this->assertCount(1, $rules['body']['rules']); - $this->assertNotEmpty($rules['body']['rules'][0]['domain']); - - $domain = $rules['body']['rules'][0]['domain']; + $domain = $this->setupFunctionDomain($functionId); $this->setupDeployment($functionId, [ 'entrypoint' => 'index.php', @@ -1764,22 +1790,7 @@ class FunctionsCustomServerTest extends Scope 'execute' => ['any'] ]); - $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => [ - Query::equal('resourceId', [$functionId])->toString(), - Query::equal('resourceType', ['function'])->toString(), - ], - ]); - - $this->assertEquals(200, $rules['headers']['status-code']); - $this->assertEquals(1, $rules['body']['total']); - $this->assertCount(1, $rules['body']['rules']); - $this->assertNotEmpty($rules['body']['rules'][0]['domain']); - - $domain = $rules['body']['rules'][0]['domain']; + $domain = $this->setupFunctionDomain($functionId); $this->setupDeployment($functionId, [ 'entrypoint' => 'index.php', @@ -1897,7 +1908,9 @@ class FunctionsCustomServerTest extends Scope $this->assertFalse($function['body']['logging']); $this->assertNotEmpty($function['body']['$id']); - $functionId = $functionId = $function['body']['$id'] ?? ''; + $functionId = $function['body']['$id'] ?? ''; + + $domain = $this->setupFunctionDomain($functionId); $this->setupDeployment($functionId, [ 'code' => $this->packageFunction('node'), @@ -1933,20 +1946,7 @@ class FunctionsCustomServerTest extends Scope }, 10000, 500); // Domain Executions test - $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => [ - Query::equal('resourceId', [$functionId])->toString(), - Query::equal('resourceType', ['function'])->toString(), - ], - ]); - - $this->assertEquals(200, $rules['headers']['status-code']); - $this->assertNotEmpty($rules['body']['rules'][0]['domain']); - - $domain = $rules['body']['rules'][0]['domain']; + $domain = $this->getFunctionDomain($functionId); $proxyClient = new Client(); $proxyClient->setEndpoint('http://' . $domain); @@ -1984,4 +1984,374 @@ class FunctionsCustomServerTest extends Scope $this->cleanupFunction($functionId); } + + public function testFunctionSpecifications() + { + // Check if the function specifications are correctly set in builds + $function = $this->createFunction([ + 'functionId' => ID::unique(), + 'runtime' => 'node-18.0', + 'name' => 'Specification Test', + 'entrypoint' => 'index.js', + 'logging' => false, + 'execute' => ['any'], + 'specification' => Specification::S_2VCPU_2GB, + 'commands' => 'echo $APPWRITE_FUNCTION_MEMORY:$APPWRITE_FUNCTION_CPUS', + ]); + + $this->assertEquals(201, $function['headers']['status-code']); + $this->assertEquals(Specification::S_2VCPU_2GB, $function['body']['specification']); + $this->assertNotEmpty($function['body']['$id']); + + $functionId = $functionId = $function['body']['$id'] ?? ''; + + $deploymentId = $this->setupDeployment($functionId, [ + 'code' => $this->packageFunction('node'), + 'activate' => true + ]); + + $this->assertEventually(function () use ($functionId, $deploymentId) { + $deployment = $this->getDeployment($functionId, $deploymentId); + $this->assertTrue(str_contains($deployment['body']['buildLogs'], '2048:2')); + }, 10000, 500); + + // Check if the function specifications are correctly set in executions + $execution = $this->createExecution($functionId); + + $this->assertEquals(201, $execution['headers']['status-code']); + $this->assertNotEmpty($execution['body']['$id']); + + $executionResponse = json_decode($execution['body']['responseBody'], true); + $this->assertEquals('2048', $executionResponse['APPWRITE_FUNCTION_MEMORY']); + $this->assertEquals('2', $executionResponse['APPWRITE_FUNCTION_CPUS']); + + $this->cleanupFunction($functionId); + } + + public function testDuplicateDeployment(): void + { + $functionId = $this->setupFunction([ + 'functionId' => ID::unique(), + 'runtime' => 'node-18.0', + 'name' => 'Duplicate Deployment Test', + 'entrypoint' => 'index.js', + 'commands' => '' + ]); + $this->assertNotEmpty($functionId); + + $deploymentId1 = $this->setupDeployment($functionId, [ + 'code' => $this->packageFunction('node'), + 'activate' => true + ]); + $this->assertNotEmpty($deploymentId1); + + $execution = $this->createExecution($functionId); + $this->assertEquals(201, $execution['headers']['status-code']); + $this->assertStringContainsString('APPWRITE_FUNCTION_ID', $execution['body']['responseBody']); + + $function = $this->updateFunction($functionId, [ + 'runtime' => 'node-18.0', + 'name' => 'Duplicate Deployment Test', + 'entrypoint' => 'index.js', + 'commands' => 'rm index.js && mv maintenance.js index.js' + ]); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertStringContainsString('maintenance.js', $function['body']['commands']); + + $deployment = $this->createDuplicateDeployment($functionId, $deploymentId1); + $this->assertEquals(202, $deployment['headers']['status-code']); + + $deploymentId2 = $deployment['body']['$id']; + $this->assertNotEmpty($deploymentId2); + + $deployment = $this->getDeployment($functionId, $deploymentId2); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertGreaterThan(0, $deployment['body']['sourceSize']); + $this->assertEquals(0, $deployment['body']['buildSize']); + $this->assertEquals($deployment['body']['sourceSize'], $deployment['body']['totalSize']); + + $this->assertEventually(function () use ($functionId, $deploymentId2) { + $function = $this->getFunction($functionId); + $this->assertEquals($deploymentId2, $function['body']['deploymentId']); + }, 50000, 500); + + $execution = $this->createExecution($functionId); + $this->assertEquals(201, $execution['headers']['status-code']); + $this->assertStringContainsString('Maintenance', $execution['body']['responseBody']); + + $deployment = $this->getDeployment($functionId, $deploymentId2); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertGreaterThan(0, $deployment['body']['sourceSize']); + $this->assertGreaterThan(0, $deployment['body']['buildSize']); + $totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize']; + $this->assertEquals($totalSize, $deployment['body']['totalSize']); + + $this->cleanupFunction($functionId); + } + + public function testUpdateDeploymentStatus(): void + { + + $functionId = $this->setupFunction([ + 'functionId' => ID::unique(), + 'runtime' => 'php-8.0', + 'name' => 'Re-activate Test', + 'entrypoint' => 'index.php', + ]); + $this->assertNotEmpty($functionId); + + + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertArrayHasKey('latestDeploymentId', $function['body']); + $this->assertArrayHasKey('latestDeploymentCreatedAt', $function['body']); + $this->assertArrayHasKey('latestDeploymentStatus', $function['body']); + $this->assertEmpty($function['body']['latestDeploymentId']); + $this->assertEmpty($function['body']['latestDeploymentCreatedAt']); + $this->assertEmpty($function['body']['latestDeploymentStatus']); + + $deploymentId1 = $this->setupDeployment($functionId, [ + 'code' => $this->packageFunction('php-cookie'), + 'activate' => true + ]); + $this->assertNotEmpty($deploymentId1); + + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertEquals($deploymentId1, $function['body']['latestDeploymentId']); + $this->assertEquals('ready', $function['body']['latestDeploymentStatus']); + + $execution = $this->createExecution($functionId, [ + 'headers' => [ 'cookie' => 'cookieName=cookieValue' ] + ]); + $this->assertEquals(201, $execution['headers']['status-code']); + $this->assertNotEmpty($execution['body']['$id']); + $this->assertStringContainsString('cookieValue', $execution['body']['responseBody']); + + $deploymentId2 = $this->setupDeployment($functionId, [ + 'code' => $this->packageFunction('php'), + 'activate' => true + ]); + $this->assertNotEmpty($deploymentId2); + + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertEquals($deploymentId2, $function['body']['latestDeploymentId']); + $this->assertEquals('ready', $function['body']['latestDeploymentStatus']); + + $execution = $this->createExecution($functionId); + $this->assertEquals(201, $execution['headers']['status-code']); + $this->assertNotEmpty($execution['body']['$id']); + $this->assertStringContainsString('UNICODE_TEST', $execution['body']['responseBody']); + + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertEquals($deploymentId2, $function['body']['deploymentId']); + $this->assertEquals($deploymentId2, $function['body']['latestDeploymentId']); + $this->assertEquals('ready', $function['body']['latestDeploymentStatus']); + + $function = $this->updateFunctionDeployment($functionId, $deploymentId1); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertEquals($deploymentId1, $function['body']['deploymentId']); + + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertEquals($deploymentId1, $function['body']['deploymentId']); + $this->assertEquals($deploymentId2, $function['body']['latestDeploymentId']); + $this->assertEquals('ready', $function['body']['latestDeploymentStatus']); + + $execution = $this->createExecution($functionId, [ + 'headers' => [ 'cookie' => 'cookieName=cookieValue' ] + ]); + $this->assertEquals(201, $execution['headers']['status-code']); + $this->assertNotEmpty($execution['body']['$id']); + $this->assertStringContainsString('cookieValue', $execution['body']['responseBody']); + + $deployment = $this->deleteDeployment($functionId, $deploymentId2); + $this->assertEquals(204, $deployment['headers']['status-code']); + + $function = $this->getFunction($functionId); + $this->assertEquals(200, $function['headers']['status-code']); + $this->assertEquals($deploymentId1, $function['body']['latestDeploymentId']); + $this->assertEquals('ready', $function['body']['latestDeploymentStatus']); + + $this->cleanupFunction($functionId); + } + + #[Retry(count: 3)] + public function testErrorPages(): void + { + // non-existent domain + $domain = 'non-existent-page.functions.localhost'; + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + + $this->assertEquals(404, $response['headers']['status-code']); + $this->assertStringContainsString('Nothing is here yet', $response['body']); + $this->assertStringContainsString('Start with this domain', $response['body']); + + // failed deployment + $functionId = $this->setupFunction([ + 'functionId' => ID::unique(), + 'name' => 'Test Error Pages', + 'runtime' => 'php-8.0', + 'entrypoint' => 'index.php', + 'timeout' => 15, + 'commands' => 'cd non-existing-directory', + 'execute' => ['any'] + ]); + + $domain = $this->setupFunctionDomain($functionId); + $proxyClient->setEndpoint('http://' . $domain); + + $deployment = $this->createDeployment($functionId, [ + 'entrypoint' => 'index.php', + 'code' => $this->packageFunction('php'), + 'activate' => true + ]); + + $this->assertEquals(202, $deployment['headers']['status-code']); + + $response = $proxyClient->call(Client::METHOD_GET, '/', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ])); + + $this->assertEquals(404, $response['headers']['status-code']); + $this->assertStringContainsString('No active deployments', $response['body']); + $this->assertStringContainsString('View deployments', $response['body']); + + // canceled deployment + $deployment = $this->createDeployment($functionId, [ + 'entrypoint' => 'index.php', + 'code' => $this->packageFunction('php'), + 'activate' => true + ]); + + $deploymentId = $deployment['body']['$id'] ?? ''; + $this->assertEquals(202, $deployment['headers']['status-code']); + + $deployment = $this->cancelDeployment($functionId, $deploymentId); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertEquals('canceled', $deployment['body']['status']); + + $response = $proxyClient->call(Client::METHOD_GET, '/', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ])); + + $this->assertEquals(404, $response['headers']['status-code']); + $this->assertStringContainsString('No active deployments', $response['body']); + $this->assertStringContainsString('View deployments', $response['body']); + + $this->cleanupFunction($functionId); + } + + public function testErrorPagesPermissions(): void + { + $functionId = $this->setupFunction([ + 'functionId' => ID::unique(), + 'name' => 'Test Error Pages', + 'runtime' => 'php-8.0', + 'entrypoint' => 'index.php', + 'timeout' => 15, + 'commands' => '', + 'execute' => ['users'] + ]); + + $domain = $this->setupFunctionDomain($functionId); + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $deploymentId = $this->setupDeployment($functionId, [ + 'code' => $this->packageFunction('php'), + 'activate' => true + ]); + $this->assertNotEmpty($deploymentId); + + $response = $proxyClient->call(Client::METHOD_GET, '/', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ])); + + $this->assertEquals(401, $response['headers']['status-code']); + $this->assertStringContainsString('Execution not permitted', $response['body']); + $this->assertStringContainsString('View settings', $response['body']); + + $this->cleanupFunction($functionId); + } + + public function testErrorPagesEmptyBody(): void + { + $functionId = $this->setupFunction([ + 'functionId' => ID::unique(), + 'name' => 'Test Error Pages', + 'runtime' => 'php-8.0', + 'entrypoint' => 'index.php', + 'timeout' => 15, + 'commands' => '', + 'execute' => ['any'] + ]); + + $domain = $this->setupFunctionDomain($functionId); + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $deploymentId = $this->setupDeployment($functionId, [ + 'code' => $this->packageFunction('php'), + 'activate' => true + ]); + $this->assertNotEmpty($deploymentId); + + $response = $proxyClient->call(Client::METHOD_GET, '/custom-response?code=404', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ])); + $this->assertEquals(404, $response['headers']['status-code']); + $this->assertStringContainsString('Error 404', $response['body']); + $this->assertStringContainsString('does not exist', $response['body']); + + $response = $proxyClient->call(Client::METHOD_GET, '/custom-response?code=504', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ])); + $this->assertEquals(504, $response['headers']['status-code']); + $this->assertStringContainsString('Error 504', $response['body']); + $this->assertStringContainsString('respond in time', $response['body']); + + $response = $proxyClient->call(Client::METHOD_GET, '/custom-response?code=400', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ])); + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertStringContainsString('Error 400', $response['body']); + $this->assertStringContainsString('unexpected client error', $response['body']); + + $response = $proxyClient->call(Client::METHOD_GET, '/custom-response?code=500', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ])); + $this->assertEquals(500, $response['headers']['status-code']); + $this->assertStringContainsString('Error 500', $response['body']); + $this->assertStringContainsString('unexpected server error', $response['body']); + + $response = $proxyClient->call(Client::METHOD_GET, '/custom-response?code=400&body=CustomError400', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ])); + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertStringContainsString('CustomError400', $response['body']); + + $response = $proxyClient->call(Client::METHOD_GET, '/custom-response?code=500&body=CustomError500', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ])); + $this->assertEquals(500, $response['headers']['status-code']); + $this->assertStringContainsString('CustomError500', $response['body']); + + $this->cleanupFunction($functionId); + } } diff --git a/tests/e2e/Services/GraphQL/AvatarsTest.php b/tests/e2e/Services/GraphQL/AvatarsTest.php index 9f3fa7a3bb..e3aaa2ce80 100644 --- a/tests/e2e/Services/GraphQL/AvatarsTest.php +++ b/tests/e2e/Services/GraphQL/AvatarsTest.php @@ -134,7 +134,7 @@ class AvatarsTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $graphQLPayload); - $this->assertEquals(29428, \strlen($qrCode['body'])); + $this->assertEquals(9169, \strlen($qrCode['body'])); return $qrCode['body']; } diff --git a/tests/e2e/Services/GraphQL/Base.php b/tests/e2e/Services/GraphQL/Base.php index 0b3250cecf..121d40156e 100644 --- a/tests/e2e/Services/GraphQL/Base.php +++ b/tests/e2e/Services/GraphQL/Base.php @@ -1568,7 +1568,7 @@ trait Base _id buildId entrypoint - size + buildSize status buildLogs } @@ -1620,7 +1620,7 @@ trait Base }'; case self::$RETRY_BUILD: return 'mutation retryBuild($functionId: String!, $deploymentId: String!, $buildId: String!) { - functionsCreateBuild(functionId: $functionId, deploymentId: $deploymentId, buildId: $buildId) { + functionsCreateDuplicateDeployment(functionId: $functionId, deploymentId: $deploymentId, buildId: $buildId) { status } }'; diff --git a/tests/e2e/Services/GraphQL/FunctionsClientTest.php b/tests/e2e/Services/GraphQL/FunctionsClientTest.php index e7e8421254..14b714d551 100644 --- a/tests/e2e/Services/GraphQL/FunctionsClientTest.php +++ b/tests/e2e/Services/GraphQL/FunctionsClientTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\GraphQL; +use Appwrite\Tests\Async; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; @@ -14,6 +15,7 @@ class FunctionsClientTest extends Scope use ProjectCustom; use SideClient; use Base; + use Async; public function testCreateFunction(): array { @@ -119,7 +121,7 @@ class FunctionsClientTest extends Scope ] ]; - while (true) { + $this->assertEventually(function () use ($projectId, $gqlPayload, &$deployment) { $deployment = $this->client->call(Client::METHOD_POST, '/graphql', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, @@ -130,18 +132,8 @@ class FunctionsClientTest extends Scope $this->assertArrayNotHasKey('errors', $deployment['body']); $deployment = $deployment['body']['data']['functionsGetDeployment']; - - if ( - $deployment['status'] === 'ready' - || $deployment['status'] === 'failed' - ) { - break; - } - - \sleep(1); - } - - $this->assertEquals('ready', $deployment['status']); + $this->assertEquals('ready', $deployment['status']); + }, 60000); return $deployment; } diff --git a/tests/e2e/Services/GraphQL/FunctionsServerTest.php b/tests/e2e/Services/GraphQL/FunctionsServerTest.php index c3606244c4..d211dcceea 100644 --- a/tests/e2e/Services/GraphQL/FunctionsServerTest.php +++ b/tests/e2e/Services/GraphQL/FunctionsServerTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\GraphQL; +use Appwrite\Tests\Async; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; @@ -14,6 +15,7 @@ class FunctionsServerTest extends Scope use ProjectCustom; use SideServer; use Base; + use Async; public function testCreateFunction(): array { @@ -117,7 +119,7 @@ class FunctionsServerTest extends Scope ] ]; - while (true) { + $this->assertEventually(function () use ($projectId, $gqlPayload, &$deployment) { $deployment = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, @@ -127,19 +129,8 @@ class FunctionsServerTest extends Scope $this->assertArrayNotHasKey('errors', $deployment['body']); $deployment = $deployment['body']['data']['functionsGetDeployment']; - - if ( - $deployment['status'] === 'ready' - || $deployment['status'] === 'failed' - ) { - break; - } - - \sleep(1); - } - - $this->assertEquals('ready', $deployment['status']); - + $this->assertEquals('ready', $deployment['status']); + }, 30000); return $deployment; } @@ -195,8 +186,8 @@ class FunctionsServerTest extends Scope 'x-appwrite-project' => $projectId, ], $this->getHeaders()), $gqlPayload); - $this->assertIsNotArray($response['body']); - $this->assertEquals(204, $response['headers']['status-code']); + $this->assertIsArray($response['body']['data']); + $this->assertEquals(200, $response['headers']['status-code']); } public function testGetFunctions(): array @@ -261,7 +252,7 @@ class FunctionsServerTest extends Scope $runtimes = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, - ], $this->getHeaders()), $gqlPayload); + ]), $gqlPayload); $this->assertIsArray($runtimes['body']['data']); $this->assertArrayNotHasKey('errors', $runtimes['body']); diff --git a/tests/e2e/Services/Health/HealthCustomServerTest.php b/tests/e2e/Services/Health/HealthCustomServerTest.php index 9d6a04abe6..04b1408cd0 100644 --- a/tests/e2e/Services/Health/HealthCustomServerTest.php +++ b/tests/e2e/Services/Health/HealthCustomServerTest.php @@ -67,24 +67,6 @@ class HealthCustomServerTest extends Scope return []; } - public function testQueueSuccess(): array - { - /** - * Test for SUCCESS - */ - $response = $this->client->call(Client::METHOD_GET, '/health/queue', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), []); - - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals('pass', $response['body']['statuses'][0]['status']); - $this->assertIsInt($response['body']['statuses'][0]['ping']); - $this->assertLessThan(100, $response['body']['statuses'][0]['ping']); - - return []; - } - public function testPubSubSuccess(): array { /** @@ -512,12 +494,12 @@ class HealthCustomServerTest extends Scope return []; } - public function testUsageSuccess() + public function testStatsResources() { /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/health/queue/stats-resources', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -529,19 +511,19 @@ class HealthCustomServerTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage?threshold=0', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/health/queue/stats-resources?threshold=0', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); $this->assertEquals(503, $response['headers']['status-code']); } - public function testUsageDumpSuccess() + public function testUsageSuccess() { /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage-dump', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/health/queue/stats-usage', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); @@ -553,7 +535,31 @@ class HealthCustomServerTest extends Scope /** * Test for FAILURE */ - $response = $this->client->call(Client::METHOD_GET, '/health/queue/usage-dump?threshold=0', array_merge([ + $response = $this->client->call(Client::METHOD_GET, '/health/queue/stats-usage?threshold=0', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + $this->assertEquals(503, $response['headers']['status-code']); + } + + public function testStatsUsageDumpSuccess() + { + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/health/queue/stats-usage-dump', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertIsInt($response['body']['size']); + $this->assertLessThan(100, $response['body']['size']); + + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_GET, '/health/queue/stats-usage-dump?threshold=0', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), []); diff --git a/tests/e2e/Services/Locale/LocaleBase.php b/tests/e2e/Services/Locale/LocaleBase.php index 0e2928004d..ee731a99e5 100644 --- a/tests/e2e/Services/Locale/LocaleBase.php +++ b/tests/e2e/Services/Locale/LocaleBase.php @@ -228,8 +228,8 @@ trait LocaleBase * Test for SUCCESS */ $languages = require(__DIR__ . '/../../../../app/config/locale/codes.php'); - $defaultCountries = require(__DIR__ . '/../../../../app/config/locale/countries.php'); - $defaultContinents = require(__DIR__ . '/../../../../app/config/locale/continents.php'); + $defaultCountries = array_keys(require(__DIR__ . '/../../../../app/config/locale/countries.php')); + $defaultContinents = array_keys(require(__DIR__ . '/../../../../app/config/locale/continents.php')); foreach ($languages as $lang) { $response = $this->client->call(Client::METHOD_GET, '/locale/countries', [ diff --git a/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php b/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php index 1b0d840f96..245eb3e8de 100644 --- a/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php +++ b/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\Messaging; +use Appwrite\Tests\Async; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; @@ -11,6 +12,8 @@ use Utopia\Database\Query; class MessagingConsoleClientTest extends Scope { + use Async; + use MessagingBase; use ProjectCustom; use SideConsole; @@ -54,15 +57,18 @@ class MessagingConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); - $logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['body']['$id'] . '/logs', \array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + // required for Cloud x Audits + $this->assertEventually(function () use ($provider) { + $logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['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->assertIsNumeric($logs['body']['total']); - $this->assertCount(2, $logs['body']['logs']); + $this->assertEquals($logs['headers']['status-code'], 200); + $this->assertIsArray($logs['body']['logs']); + $this->assertIsNumeric($logs['body']['total']); + $this->assertCount(2, $logs['body']['logs']); + }); $logs = $this->client->call(Client::METHOD_GET, '/messaging/providers/' . $provider['body']['$id'] . '/logs', \array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Migrations/MigrationsBase.php b/tests/e2e/Services/Migrations/MigrationsBase.php index e4c7ba7712..45b57d6b0c 100644 --- a/tests/e2e/Services/Migrations/MigrationsBase.php +++ b/tests/e2e/Services/Migrations/MigrationsBase.php @@ -4,13 +4,16 @@ namespace Tests\E2E\Services\Migrations; use CURLFile; use Tests\E2E\Client; +use Tests\E2E\General\UsageTest; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Services\Functions\FunctionsBase; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; +use Utopia\Database\Query; use Utopia\Migration\Resource; use Utopia\Migration\Sources\Appwrite; +use Utopia\Migration\Sources\CSV; trait MigrationsBase { @@ -20,13 +23,13 @@ trait MigrationsBase /** * @var array */ - protected static $destinationProject = []; + protected static array $destinationProject = []; /** * @param bool $fresh * @return array */ - public function getDesintationProject(bool $fresh = false): array + public function getDestinationProject(bool $fresh = false): array { if (!empty(self::$destinationProject) && !$fresh) { return self::$destinationProject; @@ -40,25 +43,25 @@ trait MigrationsBase return self::$destinationProject; } - public function performMigrationSync( - array $body, - ): array { + public function performMigrationSync(array $body): array + { $migration = $this->client->call(Client::METHOD_POST, '/migrations/appwrite', [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ], $body); $this->assertEquals(202, $migration['headers']['status-code']); $this->assertNotEmpty($migration['body']); $this->assertNotEmpty($migration['body']['$id']); - $attempts = 0; - while ($attempts < 5) { + $migrationResult = []; + + $this->assertEventually(function () use ($migration, &$migrationResult) { $response = $this->client->call(Client::METHOD_GET, '/migrations/' . $migration['body']['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -66,28 +69,24 @@ trait MigrationsBase $this->assertNotEmpty($response['body']['$id']); if ($response['body']['status'] === 'failed') { - $this->fail('Migration failed', json_encode($response['body'], JSON_PRETTY_PRINT)); + $this->fail('Migration failed' . json_encode($response['body'], JSON_PRETTY_PRINT)); } $this->assertNotEquals('failed', $response['body']['status']); + $this->assertEquals('completed', $response['body']['status']); - if ($response['body']['status'] === 'completed') { - return $response['body']; - } + $migrationResult = $response['body']; - if ($attempts === 4) { - $this->assertEquals('completed', $response['body']['status']); - } + return true; + }); - $attempts++; - sleep(5); - } + return $migrationResult; } /** * Appwrite E2E Migration Tests */ - public function testCreateAppwriteMigration() + public function testCreateAppwriteMigration(): void { $response = $this->performMigrationSync([ 'resources' => Appwrite::getSupportedResources(), @@ -105,7 +104,7 @@ trait MigrationsBase /** * Auth */ - public function testAppwriteMigrationAuthUserPassword() + public function testAppwriteMigrationAuthUserPassword(): void { $response = $this->client->call(Client::METHOD_POST, '/users', [ 'content-type' => 'application/json', @@ -144,8 +143,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/users/' . $user['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -157,8 +156,8 @@ trait MigrationsBase // Cleanup $this->client->call(Client::METHOD_DELETE, '/users/' . $user['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->client->call(Client::METHOD_DELETE, '/users/' . $user['$id'], [ @@ -168,7 +167,7 @@ trait MigrationsBase ]); } - public function testAppwriteMigrationAuthUserPhone() + public function testAppwriteMigrationAuthUserPhone(): void { $response = $this->client->call(Client::METHOD_POST, '/users', [ 'content-type' => 'application/json', @@ -206,8 +205,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/users/' . $user['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -224,12 +223,12 @@ trait MigrationsBase $this->client->call(Client::METHOD_DELETE, '/users/' . $user['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); } - public function testAppwriteMigrationAuthTeam() + public function testAppwriteMigrationAuthTeam(): void { $user = $this->client->call(Client::METHOD_POST, '/users', [ 'content-type' => 'application/json', @@ -309,8 +308,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/teams/' . $team['body']['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -320,8 +319,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/teams/' . $team['body']['$id'] . '/memberships', [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -342,8 +341,8 @@ trait MigrationsBase $this->client->call(Client::METHOD_DELETE, '/teams/' . $team['body']['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->client->call(Client::METHOD_DELETE, '/users/' . $user['body']['$id'], [ @@ -354,8 +353,8 @@ trait MigrationsBase $this->client->call(Client::METHOD_DELETE, '/users/' . $user['body']['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->client->call(Client::METHOD_DELETE, '/teams/' . $team['body']['$id'], [ @@ -366,15 +365,15 @@ trait MigrationsBase $this->client->call(Client::METHOD_DELETE, '/teams/' . $team['body']['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); } /** * Databases */ - public function testAppwriteMigrationDatabase() + public function testAppwriteMigrationDatabase(): array { $response = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', @@ -400,7 +399,6 @@ trait MigrationsBase 'apiKey' => $this->getProject()['apiKey'], ]); - $this->assertEquals('completed', $result['status']); $this->assertEquals([Resource::TYPE_DATABASE], $result['resources']); $this->assertArrayHasKey(Resource::TYPE_DATABASE, $result['statusCounters']); @@ -412,8 +410,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId, [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -426,8 +424,8 @@ trait MigrationsBase // Cleanup on destination $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); return [ @@ -438,7 +436,7 @@ trait MigrationsBase /** * @depends testAppwriteMigrationDatabase */ - public function testAppwriteMigrationDatabasesCollection(array $data) + public function testAppwriteMigrationDatabasesCollection(array $data): array { $databaseId = $data['databaseId']; @@ -506,8 +504,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -518,8 +516,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/name', [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -532,8 +530,8 @@ trait MigrationsBase // Cleanup $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); return [ @@ -545,7 +543,7 @@ trait MigrationsBase /** * @depends testAppwriteMigrationDatabasesCollection */ - public function testAppwriteMigrationDatabasesDocument(array $data) + public function testAppwriteMigrationDatabasesDocument(array $data): void { $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; @@ -579,6 +577,14 @@ trait MigrationsBase 'apiKey' => $this->getProject()['apiKey'], ]); + $finalStats = $this->client->call(Client::METHOD_GET, '/project/usage', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'startDate' => UsageTest::getYesterday(), + 'endDate' => UsageTest::getTomorrow(), + ]); + $this->assertEquals('completed', $result['status']); $this->assertEquals([Resource::TYPE_DATABASE, Resource::TYPE_COLLECTION, Resource::TYPE_ATTRIBUTE, Resource::TYPE_DOCUMENT], $result['resources']); @@ -594,8 +600,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -607,15 +613,15 @@ trait MigrationsBase // Cleanup $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); } /** * Storage */ - public function testAppwriteMigrationStorageBucket() + public function testAppwriteMigrationStorageBucket(): void { $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', [ 'content-type' => 'application/json', @@ -663,8 +669,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucket['body']['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -683,8 +689,8 @@ trait MigrationsBase // Cleanup $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucket['body']['$id'], [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucket['body']['$id'], [ @@ -694,7 +700,7 @@ trait MigrationsBase ]); } - public function testAppwriteMigrationStorageFiles() + public function testAppwriteMigrationStorageFiles(): void { $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', [ 'content-type' => 'application/json', @@ -767,8 +773,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -786,15 +792,15 @@ trait MigrationsBase $this->client->call(Client::METHOD_DELETE, '/storage/buckets/' . $bucketId . '/files/' . $fileId, [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); } /** * Functions */ - public function testAppwriteMigrationFunction() + public function testAppwriteMigrationFunction(): void { $functionId = $this->setupFunction([ 'functionId' => ID::unique(), @@ -839,8 +845,8 @@ trait MigrationsBase $response = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId, [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -856,8 +862,8 @@ trait MigrationsBase $this->assertEventually(function () use ($functionId) { $deployments = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/deployments/', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ])); $this->assertEquals(200, $deployments['headers']['status-code']); @@ -870,8 +876,8 @@ trait MigrationsBase // Attempt execution $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ], [ 'body' => 'test' ]); @@ -888,8 +894,336 @@ trait MigrationsBase $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, [ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getDesintationProject()['$id'], - 'x-appwrite-key' => $this->getDesintationProject()['apiKey'], + 'x-appwrite-project' => $this->getDestinationProject()['$id'], + 'x-appwrite-key' => $this->getDestinationProject()['apiKey'], ]); } + + /** + * Import documents from a CSV file. + */ + public function testCreateCsvMigration(): array + { + // make a database + $response = $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' => 'Test Database' + ]); + + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals('Test Database', $response['body']['name']); + + $databaseId = $response['body']['$id']; + + // make a collection + $response = $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'] + ]), [ + 'name' => 'Test collection', + 'collectionId' => ID::unique(), + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertEquals($response['body']['name'], 'Test collection'); + + $collectionId = $response['body']['$id']; + + // make attributes + $response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'name', + 'size' => 256, + 'required' => true, + ]); + + $this->assertEquals(202, $response['headers']['status-code']); + $this->assertEquals($response['body']['key'], 'name'); + $this->assertEquals($response['body']['type'], 'string'); + $this->assertEquals($response['body']['size'], 256); + $this->assertEquals($response['body']['required'], true); + + $response = $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' => 'age', + 'min' => 18, + 'max' => 65, + 'required' => true, + ]); + + $this->assertEquals(202, $response['headers']['status-code']); + $this->assertEquals($response['body']['key'], 'age'); + $this->assertEquals($response['body']['type'], 'integer'); + $this->assertEquals($response['body']['min'], 18); + $this->assertEquals($response['body']['max'], 65); + $this->assertEquals($response['body']['required'], true); + + // make a bucket, upload a file to it! + // 1. enable compression, encryption + $bucketOne = $this->client->call(Client::METHOD_POST, '/storage/buckets', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'bucketId' => ID::unique(), + 'name' => 'Test Bucket', + 'maximumFileSize' => 2000000, //2MB + 'allowedFileExtensions' => ['csv'], + 'compression' => 'gzip', + 'encryption' => true + ]); + $this->assertEquals(201, $bucketOne['headers']['status-code']); + $this->assertNotEmpty($bucketOne['body']['$id']); + + $bucketOneId = $bucketOne['body']['$id']; + + // 2. no compression and encryption + $bucketTwo = $this->client->call(Client::METHOD_POST, '/storage/buckets', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'bucketId' => ID::unique(), + 'name' => 'Test Bucket 2', + 'maximumFileSize' => 2000000, //2MB + 'allowedFileExtensions' => ['csv'], + 'compression' => 'none', + 'encryption' => false + ]); + + $this->assertNotEmpty($bucketTwo['body']['$id']); + $this->assertEquals(201, $bucketTwo['headers']['status-code']); + + $bucketTwoId = $bucketTwo['body']['$id']; + + $bucketIds = [ + 'compressed' => $bucketOneId, + 'uncompressed' => $bucketTwoId, + + // in uncompressed buckets! + 'missing-row' => $bucketTwoId, + 'missing-column' => $bucketTwoId, + 'irrelevant-column' => $bucketTwoId, + ]; + + $fileIds = []; + + foreach ($bucketIds as $label => $bucketId) { + $csvFileName = match ($label) { + 'missing-row', + 'missing-column', + 'irrelevant-column' => "{$label}.csv", + default => 'documents.csv', + }; + + $mimeType = match ($csvFileName) { + default => 'text/csv', + 'missing-row.csv' => 'text/plain', // invalid csv structure, falls back to plain text! + }; + + $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . $bucketId . '/files', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'fileId' => ID::unique(), + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/csv/'.$csvFileName), $mimeType, $csvFileName), + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals($csvFileName, $response['body']['name']); + $this->assertEquals($mimeType, $response['body']['mimeType']); + + $fileIds[$label] = $response['body']['$id']; + } + + // compressed, fail. + $compressed = $this->performCsvMigration( + [ + 'fileId' => $fileIds['compressed'], + 'bucketId' => $bucketIds['compressed'], + 'resourceId' => $databaseId . ':' . $collectionId, + ] + ); + + // fail on compressed, encrypted buckets! + $this->assertEquals(400, $compressed['body']['code']); + $this->assertEquals('storage_file_type_unsupported', $compressed['body']['type']); + $this->assertEquals('Only uncompressed, unencrypted CSV files can be used for document import.', $compressed['body']['message']); + + // missing attribute, fail in worker. + $missingColumn = $this->performCsvMigration( + [ + 'fileId' => $fileIds['missing-column'], + 'bucketId' => $bucketIds['missing-column'], + 'resourceId' => $databaseId . ':' . $collectionId, + ] + ); + + $this->assertEventually(function () use ($missingColumn, $databaseId, $collectionId) { + $migrationId = $missingColumn['body']['$id']; + $migration = $this->client->call(Client::METHOD_GET, '/migrations/'.$migrationId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $migration['headers']['status-code']); + $this->assertEquals('finished', $migration['body']['stage']); + $this->assertEquals('failed', $migration['body']['status']); + $this->assertEquals('CSV', $migration['body']['source']); + $this->assertEquals('Appwrite', $migration['body']['destination']); + $this->assertContains(Resource::TYPE_DOCUMENT, $migration['body']['resources']); + $this->assertEmpty($migration['body']['statusCounters']); + $this->assertThat( + implode("\n", $migration['body']['errors']), + $this->stringContains("CSV header mismatch. Missing attribute: 'age'") + ); + }, 60000, 500); + + // missing row data, fail in worker. + $missingColumn = $this->performCsvMigration( + [ + 'fileId' => $fileIds['missing-row'], + 'bucketId' => $bucketIds['missing-row'], + 'resourceId' => $databaseId . ':' . $collectionId, + ] + ); + + $this->assertEventually(function () use ($missingColumn, $databaseId, $collectionId) { + $migrationId = $missingColumn['body']['$id']; + $migration = $this->client->call(Client::METHOD_GET, '/migrations/'.$migrationId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $migration['headers']['status-code']); + $this->assertEquals('finished', $migration['body']['stage']); + $this->assertEquals('failed', $migration['body']['status']); + $this->assertEquals('CSV', $migration['body']['source']); + $this->assertEquals('Appwrite', $migration['body']['destination']); + $this->assertContains(Resource::TYPE_DOCUMENT, $migration['body']['resources']); + $this->assertEmpty($migration['body']['statusCounters']); + $this->assertThat( + implode("\n", $migration['body']['errors']), + $this->stringContains('CSV row does not match the number of header columns') + ); + }, 60000, 500); + + // irrelevant column - email, fail in worker. + $irrelevantColumn = $this->performCsvMigration( + [ + 'fileId' => $fileIds['irrelevant-column'], + 'bucketId' => $bucketIds['irrelevant-column'], + 'resourceId' => $databaseId . ':' . $collectionId, + ] + ); + + $this->assertEventually(function () use ($irrelevantColumn, $databaseId, $collectionId) { + $migrationId = $irrelevantColumn['body']['$id']; + $migration = $this->client->call(Client::METHOD_GET, '/migrations/'.$migrationId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $migration['headers']['status-code']); + $this->assertEquals('finished', $migration['body']['stage']); + $this->assertEquals('failed', $migration['body']['status']); + $this->assertEquals('CSV', $migration['body']['source']); + $this->assertEquals('Appwrite', $migration['body']['destination']); + $this->assertContains(Resource::TYPE_DOCUMENT, $migration['body']['resources']); + $this->assertEmpty($migration['body']['statusCounters']); + $this->assertThat( + implode("\n", $migration['body']['errors']), + $this->stringContains("CSV header mismatch. Unexpected attribute: 'email'") + ); + }, 60000, 500); + + // no compression, no encryption, pass. + $migration = $this->performCsvMigration( + [ + 'endpoint' => 'http://localhost/v1', + 'fileId' => $fileIds['uncompressed'], + 'bucketId' => $bucketIds['uncompressed'], + 'resourceId' => $databaseId . ':' . $collectionId, + ] + ); + + $this->assertEmpty($migration['body']['statusCounters']); + $this->assertEquals('CSV', $migration['body']['source']); + $this->assertEquals('pending', $migration['body']['status']); + $this->assertEquals('Appwrite', $migration['body']['destination']); + $this->assertContains(Resource::TYPE_DOCUMENT, $migration['body']['resources']); + + return [ + 'databaseId' => $databaseId, + 'collectionId' => $collectionId, + 'migrationId' => $migration['body']['$id'], + ]; + } + + /** + * @depends testCreateCsvMigration + */ + public function testImportSuccessful(array $response): void + { + $databaseId = $response['databaseId']; + $collectionId = $response['collectionId']; + $migrationId = $response['migrationId']; + + $documentsCountInCSV = 100; + + // get migration stats + $this->assertEventually(function () use ($migrationId, $databaseId, $collectionId, $documentsCountInCSV) { + $migration = $this->client->call(Client::METHOD_GET, '/migrations/'.$migrationId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $migration['headers']['status-code']); + $this->assertEquals('finished', $migration['body']['stage']); + $this->assertEquals('completed', $migration['body']['status']); + $this->assertEquals('CSV', $migration['body']['source']); + $this->assertEquals('Appwrite', $migration['body']['destination']); + $this->assertContains(Resource::TYPE_DOCUMENT, $migration['body']['resources']); + $this->assertArrayHasKey(Resource::TYPE_DOCUMENT, $migration['body']['statusCounters']); + $this->assertEquals($documentsCountInCSV, $migration['body']['statusCounters'][Resource::TYPE_DOCUMENT]['success']); + }, 60000, 500); + + // get documents count + $documents = $this->client->call(Client::METHOD_GET, '/databases/'.$databaseId.'/collections/'.$collectionId.'/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + // there should be only 100! + Query::limit(150)->toString() + ] + ]); + + $this->assertEquals(200, $documents['headers']['status-code']); + $this->assertIsArray($documents['body']['documents']); + $this->assertIsNumeric($documents['body']['total']); + $this->assertEquals($documentsCountInCSV, $documents['body']['total']); + } + + private function performCsvMigration(array $body): array + { + return $this->client->call(Client::METHOD_POST, '/migrations/csv', [ + 'content-type' => 'application/json', + 'x-appwrite-key' => $this->getProject()['apiKey'], + 'x-appwrite-project' => $this->getProject()['$id'], + ], $body); + } } diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 48210435e7..afd1189496 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -4,6 +4,7 @@ namespace Tests\E2E\Services\Projects; use Appwrite\Auth\Auth; use Appwrite\Extend\Exception; +use Appwrite\Tests\Async; use Tests\E2E\Client; use Tests\E2E\General\UsageTest; use Tests\E2E\Scopes\ProjectConsole; @@ -13,12 +14,14 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; +use Utopia\System\System; class ProjectsConsoleClientTest extends Scope { use ProjectsBase; use ProjectConsole; use SideClient; + use Async; /** * @group smtpAndTemplates @@ -47,7 +50,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Project Test', 'teamId' => $team['body']['$id'], - 'region' => 'default', + 'region' => System::getEnv('_APP_REGION', 'default') ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -87,7 +90,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => '', 'teamId' => $team['body']['$id'], - 'region' => 'default' + 'region' => System::getEnv('_APP_REGION', 'default') ]); $this->assertEquals(400, $response['headers']['status-code']); @@ -98,7 +101,7 @@ class ProjectsConsoleClientTest extends Scope ], $this->getHeaders()), [ 'projectId' => ID::unique(), 'name' => 'Project Test', - 'region' => 'default' + 'region' => System::getEnv('_APP_REGION', 'default') ]); $this->assertEquals(401, $response['headers']['status-code']); @@ -127,7 +130,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => $projectId, 'name' => 'Project Duplicate', 'teamId' => $teamId, - 'region' => 'default' + 'region' => System::getEnv('_APP_REGION', 'default') ]); $this->assertEquals(409, $response['headers']['status-code']); @@ -176,7 +179,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Team 1 Project', 'teamId' => $team1, - 'region' => 'default', + 'region' => System::getEnv('_APP_REGION', 'default'), ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -275,7 +278,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Project Test 2', 'teamId' => $team['body']['$id'], - 'region' => 'default' + 'region' => System::getEnv('_APP_REGION', 'default') ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -485,6 +488,8 @@ class ProjectsConsoleClientTest extends Scope $this->assertIsNumeric($response['body']['usersTotal']); $this->assertIsNumeric($response['body']['filesStorageTotal']); $this->assertIsNumeric($response['body']['deploymentStorageTotal']); + $this->assertIsNumeric($response['body']['authPhoneTotal']); + $this->assertIsNumeric($response['body']['authPhoneEstimate']); /** @@ -1409,18 +1414,20 @@ class ProjectsConsoleClientTest extends Scope /** * List sessions */ - $response = $this->client->call(Client::METHOD_GET, '/account/sessions', [ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $id, - 'Cookie' => $sessionCookie, - ]); + $this->assertEventually(function () use ($id, $sessionCookie, $sessionId2) { + $response = $this->client->call(Client::METHOD_GET, '/account/sessions', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'Cookie' => $sessionCookie, + ]); - $this->assertEquals(200, $response['headers']['status-code']); - $sessions = $response['body']['sessions']; + $this->assertEquals(200, $response['headers']['status-code']); + $sessions = $response['body']['sessions']; - $this->assertEquals(1, count($sessions)); - $this->assertEquals($sessionId2, $sessions[0]['$id']); + $this->assertEquals(1, count($sessions)); + $this->assertEquals($sessionId2, $sessions[0]['$id']); + }); /** * Reset Limit @@ -2036,7 +2043,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Project Test', 'teamId' => $team['body']['$id'], - 'region' => 'default' + 'region' => System::getEnv('_APP_REGION', 'default') ]); $this->assertEquals(201, $project['headers']['status-code']); @@ -2129,7 +2136,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Project Test', 'teamId' => $team['body']['$id'], - 'region' => 'default' + 'region' => System::getEnv('_APP_REGION', 'default') ]); $this->assertEquals(201, $project['headers']['status-code']); @@ -3727,11 +3734,11 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'teamId' => ID::unique(), - 'name' => 'Amating Team', + 'name' => 'Amazing Team', ]); $this->assertEquals(201, $team['headers']['status-code']); - $this->assertEquals('Amating Team', $team['body']['name']); + $this->assertEquals('Amazing Team', $team['body']['name']); $this->assertNotEmpty($team['body']['$id']); $teamId = $team['body']['$id']; @@ -3743,7 +3750,7 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Amazing Project', 'teamId' => $teamId, - 'region' => 'default' + 'region' => System::getEnv('_APP_REGION', 'default') ]); $this->assertEquals(201, $project['headers']['status-code']); @@ -3794,6 +3801,115 @@ class ProjectsConsoleClientTest extends Scope return $data; } + public function testDeleteSharedProject(): void + { + $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'teamId' => ID::unique(), + 'name' => 'Amazing Team', + ]); + + $teamId = $team['body']['$id']; + + // Ensure deleting one project does not affect another project + $project1 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'projectId' => ID::unique(), + 'name' => 'Amazing Project 1', + 'teamId' => $teamId, + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + $project2 = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'projectId' => ID::unique(), + 'name' => 'Amazing Project 2', + 'teamId' => $teamId, + 'region' => System::getEnv('_APP_REGION', 'default') + ]); + + $project1Id = $project1['body']['$id']; + $project2Id = $project2['body']['$id']; + + // Create user in each project + $key1 = $this->client->call(Client::METHOD_POST, '/projects/' . $project1Id . '/keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test', + 'scopes' => ['users.read', 'users.write'], + ]); + + $user1 = $this->client->call(Client::METHOD_POST, '/users', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project1Id, + 'x-appwrite-key' => $key1['body']['secret'], + ], [ + 'userId' => ID::unique(), + 'email' => 'test1@appwrite.io', + 'password' => 'password', + ]); + + $this->assertEquals(201, $user1['headers']['status-code']); + + $key2 = $this->client->call(Client::METHOD_POST, '/projects/' . $project2Id . '/keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'name' => 'Key Test', + 'scopes' => ['users.read', 'users.write'], + ]); + + $user2 = $this->client->call(Client::METHOD_POST, '/users', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2Id, + 'x-appwrite-key' => $key2['body']['secret'], + ], [ + 'userId' => ID::unique(), + 'email' => 'test2@appwrite.io', + 'password' => 'password', + ]); + + $this->assertEquals(201, $user2['headers']['status-code']); + + // Delete project 1 + $project1 = $this->client->call(Client::METHOD_DELETE, '/projects/' . $project1Id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(204, $project1['headers']['status-code']); + + \sleep(3); + + // Ensure project 2 user is still there + $user2 = $this->client->call(Client::METHOD_GET, '/users/' . $user2['body']['$id'], [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2Id, + 'x-appwrite-key' => $key2['body']['secret'], + ]); + + $this->assertEquals(200, $user2['headers']['status-code']); + + // Create another user in project 2 in case read hits stale cache + $user3 = $this->client->call(Client::METHOD_POST, '/users', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $project2Id, + 'x-appwrite-key' => $key2['body']['secret'], + ], [ + 'userId' => ID::unique(), + 'email' => 'test3@appwrite.io' + ]); + + $this->assertEquals(201, $user3['headers']['status-code']); + } + /** * @depends testCreateProject */ @@ -3808,10 +3924,14 @@ class ProjectsConsoleClientTest extends Scope 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'key' => 'APP_TEST', - 'value' => 'TESTINGVALUE' + 'value' => 'TESTINGVALUE', + 'secret' => false ]); $this->assertEquals(201, $variable['headers']['status-code']); + $this->assertEquals('APP_TEST', $variable['body']['key']); + $this->assertEquals('TESTINGVALUE', $variable['body']['value']); + $this->assertFalse($variable['body']['secret']); $variableId = $variable['body']['$id']; // test for secret variable @@ -3932,6 +4052,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals("APP_TEST_1", $response['body']['key']); $this->assertEmpty($response['body']['value']); + $this->assertTrue($response['body']['secret']); /** * Test for FAILURE @@ -4003,6 +4124,17 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals("APP_TEST_UPDATE_1", $variable['body']['key']); $this->assertEmpty($variable['body']['value']); + $response = $this->client->call(Client::METHOD_PUT, '/project/variables/' . $data['secretVariableId'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectId'], + 'x-appwrite-mode' => 'admin', + ], $this->getHeaders()), [ + 'key' => 'APP_TEST_UPDATE_1', + 'secret' => false, + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + $response = $this->client->call(Client::METHOD_GET, '/project/variables', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $data['projectId'], diff --git a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php index cc976b78f6..6d9431290f 100644 --- a/tests/e2e/Services/Projects/ProjectsCustomServerTest.php +++ b/tests/e2e/Services/Projects/ProjectsCustomServerTest.php @@ -24,25 +24,79 @@ class ProjectsCustomServerTest extends Scope 'cookie' => 'a_session_console=' . $this->getRoot()['session'], ]); - $response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [ - 'resourceType' => 'api', + $response = $this->client->call(Client::METHOD_POST, '/proxy/rules/api', $headers, [ 'domain' => 'api.appwrite.test', ]); $this->assertEquals(201, $response['headers']['status-code']); + $response = $this->client->call(Client::METHOD_POST, '/proxy/rules/api', $headers, [ + 'resourceType' => 'api', + 'domain' => 'abc.test.io', + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + // duplicate rule + $response2 = $this->client->call(Client::METHOD_POST, '/proxy/rules/api', $headers, [ + 'domain' => 'abc.test.io', + ]); + + $this->assertEquals(409, $response2['headers']['status-code']); + $response = $this->client->call(Client::METHOD_DELETE, '/proxy/rules/' . $response['body']['$id'], $headers); $this->assertEquals(204, $response['headers']['status-code']); - // prevent functions domain $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); - $response = $this->client->call(Client::METHOD_POST, '/proxy/rules', $headers, [ - 'resourceType' => 'api', + $response = $this->client->call(Client::METHOD_POST, '/proxy/rules/api', $headers, [ 'domain' => $functionsDomain, ]); $this->assertEquals(400, $response['headers']['status-code']); + + + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + + $response = $this->client->call(Client::METHOD_POST, '/proxy/rules/api', $headers, [ + 'domain' => $sitesDomain, + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // prevent functions domain + $response = $this->client->call(Client::METHOD_POST, '/proxy/rules/function', $headers, [ + 'domain' => $functionsDomain, + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + // prevent sites domain + $response = $this->client->call(Client::METHOD_POST, '/proxy/rules/site', $headers, [ + 'domain' => $sitesDomain, + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + $mainDomain = System::getEnv('_APP_DOMAIN', ''); + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + + $deniedDomains = [ + $mainDomain, + $sitesDomain, + $functionsDomain, + 'localhost', + APP_HOSTNAME_INTERNAL, + ]; + + foreach ($deniedDomains as $deniedDomain) { + $response = $this->client->call(Client::METHOD_POST, '/proxy/rules/api', $headers, [ + 'domain' => $deniedDomain, + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + } } } diff --git a/tests/e2e/Services/Proxy/ProxyBase.php b/tests/e2e/Services/Proxy/ProxyBase.php new file mode 100644 index 0000000000..44e015b751 --- /dev/null +++ b/tests/e2e/Services/Proxy/ProxyBase.php @@ -0,0 +1,297 @@ +<?php + +namespace Tests\E2E\Services\Proxy; + +use Appwrite\ID; +use Appwrite\Tests\Async; +use CURLFile; +use Tests\E2E\Client; +use Utopia\CLI\Console; + +trait ProxyBase +{ + use Async; + + protected function listRules(array $params = []): mixed + { + $rule = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $rule; + } + + protected function createAPIRule(string $domain): mixed + { + $rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/api', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'domain' => $domain, + ]); + + return $rule; + } + + protected function updateRuleVerification(string $ruleId): mixed + { + $rule = $this->client->call(Client::METHOD_PATCH, '/proxy/rules/' . $ruleId . '/verification', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + return $rule; + } + + protected function createSiteRule(string $domain, string $siteId, string $branch = ''): mixed + { + $rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/site', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'domain' => $domain, + 'siteId' => $siteId, + 'branch' => $branch, + ]); + + return $rule; + } + + protected function getRule(string $ruleId): mixed + { + $rule = $this->client->call(Client::METHOD_GET, '/proxy/rules/' . $ruleId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + return $rule; + } + + protected function createRedirectRule(string $domain, string $url, int $statusCode): mixed + { + $rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/redirect', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'domain' => $domain, + 'url' => $url, + 'statusCode' => $statusCode, + ]); + + return $rule; + } + + protected function createFunctionRule(string $domain, string $functionId, string $branch = ''): mixed + { + $rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/function', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'domain' => $domain, + 'functionId' => $functionId, + 'branch' => $branch, + ]); + + return $rule; + } + + protected function deleteRule(string $ruleId): mixed + { + $rule = $this->client->call(Client::METHOD_DELETE, '/proxy/rules/' . $ruleId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + return $rule; + } + + protected function setupAPIRule(string $domain): string + { + $rule = $this->createAPIRule($domain); + + $this->assertEquals(201, $rule['headers']['status-code'], 'Failed to setup rule: ' . \json_encode($rule)); + + return $rule['body']['$id']; + } + + protected function setupRedirectRule(string $domain, string $url, int $statusCode): string + { + $rule = $this->createRedirectRule($domain, $url, $statusCode); + + $this->assertEquals(201, $rule['headers']['status-code'], 'Failed to setup rule: ' . \json_encode($rule)); + + return $rule['body']['$id']; + } + + protected function setupFunctionRule(string $domain, string $functionId, string $branch = ''): string + { + $rule = $this->createFunctionRule($domain, $functionId, $branch); + + $this->assertEquals(201, $rule['headers']['status-code'], 'Failed to setup rule: ' . \json_encode($rule)); + + return $rule['body']['$id']; + } + + protected function setupSiteRule(string $domain, string $siteId, string $branch = ''): string + { + $rule = $this->createSiteRule($domain, $siteId, $branch); + + $this->assertEquals(201, $rule['headers']['status-code'], 'Failed to setup rule: ' . \json_encode($rule)); + + return $rule['body']['$id']; + } + + protected function cleanupRule(string $ruleId): void + { + $rule = $this->deleteRule($ruleId); + $this->assertEquals(204, $rule['headers']['status-code'], 'Failed to cleanup rule: ' . \json_encode($rule)); + } + + protected function cleanupSite(string $siteId): void + { + $site = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(204, $site['headers']['status-code'], 'Failed to cleanup site: ' . \json_encode($site)); + } + + protected function cleanupFunction(string $functionId): void + { + $function = $this->client->call(Client::METHOD_DELETE, '/functions/' . $functionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(204, $function['headers']['status-code'], 'Failed to cleanup function: ' . \json_encode($function)); + } + + protected function setupSite(): mixed + { + // Site + $site = $this->client->call(Client::METHOD_POST, '/sites', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'siteId' => ID::unique(), + 'name' => 'Proxy site', + 'framework' => 'other', + 'adapter' => 'static', + 'buildRuntime' => 'static-1', + 'outputDirectory' => './', + 'buildCommand' => '', + 'installCommand' => '', + 'fallbackFile' => '', + ]); + + $this->assertEquals($site['headers']['status-code'], 201, 'Setup site failed with status code: ' . $site['headers']['status-code'] . ' and response: ' . json_encode($site['body'], JSON_PRETTY_PRINT)); + + $siteId = $site['body']['$id']; + + // Deployment + $deployment = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'code' => $this->packageSite('static'), + 'activate' => 'true' + ]); + + $this->assertEquals($deployment['headers']['status-code'], 202, 'Setup deployment failed with status code: ' . $deployment['headers']['status-code'] . ' and response: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + $deploymentId = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($siteId, $deploymentId) { + $site = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertEquals($deploymentId, $site['body']['deploymentId'], 'Deployment is not activated, deployment: ' . json_encode($site['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + return ['siteId' => $siteId, 'deploymentId' => $deploymentId]; + } + + protected function setupFunction(): mixed + { + // Function + $function = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'functionId' => ID::unique(), + 'runtime' => 'node-18.0', + 'name' => 'Proxy Function', + 'entrypoint' => 'index.js', + 'commands' => '', + 'execute' => ['any'] + ]); + + $this->assertEquals($function['headers']['status-code'], 201, 'Setup function failed with status code: ' . $function['headers']['status-code'] . ' and response: ' . json_encode($function['body'], JSON_PRETTY_PRINT)); + + $functionId = $function['body']['$id']; + + // Deployment + $deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'code' => $this->packageFunction('node'), + 'activate' => 'true' + ]); + + $this->assertEquals($deployment['headers']['status-code'], 202, 'Setup deployment failed with status code: ' . $deployment['headers']['status-code'] . ' and response: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + $deploymentId = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($functionId, $deploymentId) { + $function = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertEquals($deploymentId, $function['body']['deploymentId'], 'Deployment is not activated, deployment: ' . json_encode($function['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + return ['functionId' => $functionId, 'deploymentId' => $deploymentId]; + } + + private function packageSite(string $site): CURLFile + { + $stdout = ''; + $stderr = ''; + + $folderPath = realpath(__DIR__ . '/../../../resources/sites') . "/$site"; + $tarPath = "$folderPath/code.tar.gz"; + + Console::execute("cd $folderPath && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr); + + if (filesize($tarPath) > 1024 * 1024 * 5) { + throw new \Exception('Code package is too large. Use the chunked upload method instead.'); + } + + return new CURLFile($tarPath, 'application/x-gzip', \basename($tarPath)); + } + + private function packageFunction(string $function): CURLFile + { + $stdout = ''; + $stderr = ''; + + $folderPath = realpath(__DIR__ . '/../../../resources/functions') . "/$function"; + $tarPath = "$folderPath/code.tar.gz"; + + Console::execute("cd $folderPath && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr); + + if (filesize($tarPath) > 1024 * 1024 * 5) { + throw new \Exception('Code package is too large. Use the chunked upload method instead.'); + } + + return new CURLFile($tarPath, 'application/x-gzip', \basename($tarPath)); + } +} diff --git a/tests/e2e/Services/Proxy/ProxyCustomServerTest.php b/tests/e2e/Services/Proxy/ProxyCustomServerTest.php new file mode 100644 index 0000000000..0ac2d9c186 --- /dev/null +++ b/tests/e2e/Services/Proxy/ProxyCustomServerTest.php @@ -0,0 +1,509 @@ +<?php + +namespace Tests\E2E\Services\Proxy; + +use Tests\E2E\Client; +use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\SideServer; +use Utopia\App; +use Utopia\Database\Query; + +class ProxyCustomServerTest extends Scope +{ + use ProxyBase; + use ProjectCustom; + use SideServer; + + public function testCreateRule(): void + { + $domain = \uniqid() . '-api.myapp.com'; + $rule = $this->createAPIRule($domain); + + $this->assertEquals(201, $rule['headers']['status-code']); + $this->assertEquals($domain, $rule['body']['domain']); + $this->assertEquals('manual', $rule['body']['trigger']); + $this->assertArrayHasKey('$id', $rule['body']); + $this->assertArrayHasKey('domain', $rule['body']); + $this->assertArrayHasKey('type', $rule['body']); + $this->assertArrayHasKey('redirectUrl', $rule['body']); + $this->assertArrayHasKey('redirectStatusCode', $rule['body']); + $this->assertArrayHasKey('deploymentResourceType', $rule['body']); + $this->assertArrayHasKey('deploymentId', $rule['body']); + $this->assertArrayHasKey('deploymentResourceId', $rule['body']); + $this->assertArrayHasKey('deploymentVcsProviderBranch', $rule['body']); + $this->assertArrayHasKey('logs', $rule['body']); + $this->assertArrayHasKey('renewAt', $rule['body']); + + $ruleId = $rule['body']['$id']; + + $rule = $this->createAPIRule($domain); + $this->assertEquals(409, $rule['headers']['status-code']); + + $rule = $this->deleteRule($ruleId); + + $this->assertEquals(204, $rule['headers']['status-code']); + } + + public function testCreateRuleSetup(): void + { + $ruleId = $this->setupAPIRule(\uniqid() . '-api2.myapp.com'); + $this->cleanupRule($ruleId); + } + + public function testCreateRuleApex(): void + { + $domain = \uniqid() . '.com'; + $rule = $this->createAPIRule($domain); + $this->assertEquals(201, $rule['headers']['status-code']); + $this->assertEquals('created', $rule['body']['status']); + } + + public function testCreateRuleVcs(): void + { + $domain = \uniqid() . '-vcs.myapp.com'; + + $rule = $this->createAPIRule('commit-' . $domain); + $this->assertEquals(400, $rule['headers']['status-code']); + + $rule = $this->createAPIRule('branch-' . $domain); + $this->assertEquals(400, $rule['headers']['status-code']); + + $rule = $this->createAPIRule('anything-' . $domain); + $this->assertEquals(201, $rule['headers']['status-code']); + $this->cleanupRule($rule['body']['$id']); + } + + public function testCreateAPIRule(): void + { + $domain = \uniqid() . '-api.custom.localhost'; + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + // We should ideally assert 400, but server allows unknown domains, and serves API by default + $response = $proxyClient->call(Client::METHOD_GET, '/versions'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(APP_VERSION_STABLE, $response['body']['server']); + + $ruleId = $this->setupAPIRule($domain); + + $this->assertNotEmpty($ruleId); + + $response = $proxyClient->call(Client::METHOD_GET, '/versions'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(APP_VERSION_STABLE, $response['body']['server']); + + $this->cleanupRule($ruleId); + + $rule = $this->createAPIRule('http://' . $domain); + $this->assertEquals(400, $rule['headers']['status-code']); + + $rule = $this->createAPIRule('https://' . $domain); + $this->assertEquals(400, $rule['headers']['status-code']); + + // Unexpected I would say, but it is the current behaviour + $rule = $this->createAPIRule('wss://' . $domain); + $this->assertEquals(201, $rule['headers']['status-code']); + $this->cleanupRule($rule['body']['$id']); + + // Unexpected I would say, but it is the current behaviour + $rule = $this->createAPIRule($domain . '/some-path'); + $this->assertEquals(201, $rule['headers']['status-code']); + $this->cleanupRule($rule['body']['$id']); + } + + public function testCreateRedirectRule(): void + { + $domain = \uniqid() . '-redirect.custom.localhost'; + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://appwrite'); + $proxyClient->addHeader('x-appwrite-hostname', $domain); + + $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); + $this->assertNotEmpty($ruleId); + + $response = $proxyClient->call(Client::METHOD_GET, '/todos/1'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['id']); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(1, $response['body']['id']); + + $response = $proxyClient->call(Client::METHOD_GET, '/', followRedirects: false); + $this->assertEquals(301, $response['headers']['status-code']); + $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); + $this->assertNotEmpty($ruleId); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://appwrite'); + $proxyClient->addHeader('x-appwrite-hostname', $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/', followRedirects: false); + $this->assertEquals(307, $response['headers']['status-code']); + $this->assertEquals('https://jsonplaceholder.typicode.com/todos/1', $response['headers']['location']); + + $this->cleanupRule($ruleId); + } + + public function testCreateFunctionRule(): void + { + $domain = \uniqid() . '-function.custom.localhost'; + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://appwrite'); + $proxyClient->addHeader('x-appwrite-hostname', $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/ping'); + $this->assertEquals(404, $response['headers']['status-code']); + + $setup = $this->setupFunction(); + $functionId = $setup['functionId']; + $deploymentId = $setup['deploymentId']; + + $this->assertNotEmpty($functionId); + $this->assertNotEmpty($deploymentId); + + $ruleId = $this->setupFunctionRule($domain, $functionId); + $this->assertNotEmpty($ruleId); + + $response = $proxyClient->call(Client::METHOD_GET, '/ping'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($functionId, $response['body']['APPWRITE_FUNCTION_ID']); + + $this->cleanupRule($ruleId); + + $this->cleanupFunction($functionId); + + $this->assertEventually(function () use ($functionId, $deploymentId) { + $rules = $this->listRules([ + 'queries' => [ + Query::limit(1)->toString(), + Query::equal('type', ['deployment'])->toString(), + Query::equal('deploymentResourceType', ['function'])->toString(), + Query::equal('deploymentResourceId', [$functionId])->toString(), + ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(0, $rules['body']['total']); + $this->assertCount(0, $rules['body']['rules']); + + $rules = $this->listRules([ + 'queries' => [ + Query::limit(1)->toString(), + Query::equal('type', ['deployment'])->toString(), + Query::equal('deploymentId', [$deploymentId])->toString() + ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(0, $rules['body']['total']); + $this->assertCount(0, $rules['body']['rules']); + }); + } + + public function testCreateSiteRule(): void + { + $domain = \uniqid() . '-site.custom.localhost'; + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://appwrite'); + $proxyClient->addHeader('x-appwrite-hostname', $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/contact'); + $this->assertEquals(404, $response['headers']['status-code']); + + $setup = $this->setupSite(); + $siteId = $setup['siteId']; + $deploymentId = $setup['deploymentId']; + + $this->assertNotEmpty($siteId); + $this->assertNotEmpty($deploymentId); + + $ruleId = $this->setupSiteRule($domain, $siteId); + $this->assertNotEmpty($ruleId); + + $response = $proxyClient->call(Client::METHOD_GET, '/contact'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString('Contact page', $response['body']); + + $rules = $this->listRules([ + 'queries' => [ + Query::limit(1)->toString(), + Query::equal('trigger', ['deployment'])->toString(), + Query::equal('type', ['deployment'])->toString(), + Query::equal('deploymentResourceType', ['site'])->toString(), + Query::equal('deploymentResourceId', [$siteId])->toString(), + ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertGreaterThan(0, $rules['body']['total']); + + $this->cleanupRule($ruleId); + + $this->cleanupSite($siteId); + + $this->assertEventually(function () use ($siteId, $deploymentId) { + $rules = $this->listRules([ + 'queries' => [ + Query::limit(1)->toString(), + Query::equal('type', ['deployment'])->toString(), + Query::equal('deploymentResourceType', ['site'])->toString(), + Query::equal('deploymentResourceId', [$siteId])->toString(), + ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(0, $rules['body']['total']); + $this->assertCount(0, $rules['body']['rules']); + + $rules = $this->listRules([ + 'queries' => [ + Query::limit(1)->toString(), + Query::equal('type', ['deployment'])->toString(), + Query::equal('deploymentId', [$deploymentId])->toString() + ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(0, $rules['body']['total']); + $this->assertCount(0, $rules['body']['rules']); + }); + } + + public function testCreateSiteBranchRule(): void + { + $domain = \uniqid() . '-site-branch.custom.localhost'; + + $setup = $this->setupSite(); + $siteId = $setup['siteId']; + $deploymentId = $setup['deploymentId']; + + $this->assertNotEmpty($siteId); + $this->assertNotEmpty($deploymentId); + + $ruleId = $this->setupSiteRule($domain, $siteId, 'dev'); + $this->assertNotEmpty($ruleId); + + $rule = $this->getRule($ruleId); + $this->assertEquals(200, $rule['headers']['status-code']); + + $this->cleanupRule($ruleId); + } + + public function testCreateFunctionBranchRule(): void + { + $domain = \uniqid() . '-function-branch.custom.localhost'; + + $setup = $this->setupFunction(); + $functionId = $setup['functionId']; + $deploymentId = $setup['deploymentId']; + + $this->assertNotEmpty($functionId); + $this->assertNotEmpty($deploymentId); + + $ruleId = $this->setupFunctionRule($domain, $functionId, 'dev'); + $this->assertNotEmpty($ruleId); + + $rule = $this->getRule($ruleId); + $this->assertEquals(200, $rule['headers']['status-code']); + + $this->cleanupRule($ruleId); + + $this->cleanupFunction($functionId); + } + + public function testUpdateRule(): void + { + // Create function appwrite-network domain + $domain = \uniqid() . '-cname-api.' . App::getEnv('_APP_DOMAIN_FUNCTIONS'); + + $rule = $this->createAPIRule($domain); + $this->assertEquals(201, $rule['headers']['status-code']); + $this->assertEquals('verified', $rule['body']['status']); + + $this->cleanupRule($rule['body']['$id']); + + // Create site appwrite-network domain + $domain = \uniqid() . '-cname-api.' . App::getEnv('_APP_DOMAIN_SITES'); + + $rule = $this->createAPIRule($domain); + $this->assertEquals(201, $rule['headers']['status-code']); + $this->assertEquals('verified', $rule['body']['status']); + + $this->cleanupRule($rule['body']['$id']); + + // Create + update + $domain = \uniqid() . '-cname-api.custom.com'; + + $rule = $this->createAPIRule($domain); + $this->assertEquals(201, $rule['headers']['status-code']); + $this->assertEquals('created', $rule['body']['status']); + + $ruleId = $rule['body']['$id']; + + $rule = $this->updateRuleVerification($ruleId); + $this->assertEquals(400, $rule['headers']['status-code']); + + $this->cleanupRule($ruleId); + } + + public function testGetRule() + { + $domain = \uniqid() . '-get.custom.localhost'; + $ruleId = $this->setupAPIRule($domain); + + $this->assertNotEmpty($ruleId); + + $rule = $this->getRule($ruleId); + $this->assertEquals(200, $rule['headers']['status-code']); + $this->assertEquals($domain, $rule['body']['domain']); + $this->assertEquals('manual', $rule['body']['trigger']); + $this->assertArrayHasKey('$id', $rule['body']); + $this->assertArrayHasKey('domain', $rule['body']); + $this->assertArrayHasKey('type', $rule['body']); + $this->assertArrayHasKey('redirectUrl', $rule['body']); + $this->assertArrayHasKey('redirectStatusCode', $rule['body']); + $this->assertArrayHasKey('deploymentResourceType', $rule['body']); + $this->assertArrayHasKey('deploymentId', $rule['body']); + $this->assertArrayHasKey('deploymentResourceId', $rule['body']); + $this->assertArrayHasKey('deploymentVcsProviderBranch', $rule['body']); + $this->assertArrayHasKey('logs', $rule['body']); + $this->assertArrayHasKey('renewAt', $rule['body']); + + $this->cleanupRule($ruleId); + } + + public function testListRules() + { + $rules = $this->listRules(); + $this->assertEquals(200, $rules['headers']['status-code']); + foreach ($rules['body']['rules'] as $rule) { + $rule = $this->deleteRule($rule['$id']); + $this->assertEquals(204, $rule['headers']['status-code']); + } + + $rules = $this->listRules(); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(0, $rules['body']['total']); + $this->assertCount(0, $rules['body']['rules']); + + $rule1Domain = \uniqid() . '-list1.custom.localhost'; + $rule1Id = $this->setupAPIRule($rule1Domain); + $this->assertNotEmpty($rule1Id); + + $rules = $this->listRules(); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(1, $rules['body']['total']); + $this->assertCount(1, $rules['body']['rules']); + $this->assertEquals($rule1Domain, $rules['body']['rules'][0]['domain']); + + $this->assertEquals('manual', $rules['body']['rules'][0]['trigger']); + $this->assertArrayHasKey('$id', $rules['body']['rules'][0]); + $this->assertArrayHasKey('domain', $rules['body']['rules'][0]); + $this->assertArrayHasKey('type', $rules['body']['rules'][0]); + $this->assertArrayHasKey('redirectUrl', $rules['body']['rules'][0]); + $this->assertArrayHasKey('redirectStatusCode', $rules['body']['rules'][0]); + $this->assertArrayHasKey('deploymentResourceType', $rules['body']['rules'][0]); + $this->assertArrayHasKey('deploymentId', $rules['body']['rules'][0]); + $this->assertArrayHasKey('deploymentResourceId', $rules['body']['rules'][0]); + $this->assertArrayHasKey('deploymentVcsProviderBranch', $rules['body']['rules'][0]); + $this->assertArrayHasKey('logs', $rules['body']['rules'][0]); + $this->assertArrayHasKey('renewAt', $rules['body']['rules'][0]); + + $rule2Domain = \uniqid() . '-list1.custom.localhost'; + $rule2Id = $this->setupAPIRule($rule2Domain); + $this->assertNotEmpty($rule2Id); + + $rules = $this->listRules(); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(2, $rules['body']['total']); + $this->assertCount(2, $rules['body']['rules']); + + $rules = $this->listRules([ + 'queries' => [ + Query::limit(1)->toString() + ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(2, $rules['body']['total']); + $this->assertCount(1, $rules['body']['rules']); + + $rules = $this->listRules([ + 'queries' => [ + Query::equal('$id', [$rule1Id])->toString() + ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertCount(1, $rules['body']['rules']); + $this->assertEquals($rule1Domain, $rules['body']['rules'][0]['domain']); + + $rules = $this->listRules([ + 'queries' => [ + Query::orderDesc('$id')->toString() + ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertCount(2, $rules['body']['rules']); + $this->assertEquals($rule2Id, $rules['body']['rules'][0]['$id']); + + $rules = $this->listRules([ + 'queries' => [ + Query::equal('domain', [$rule2Domain])->toString() + ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertCount(1, $rules['body']['rules']); + $this->assertEquals($rule2Id, $rules['body']['rules'][0]['$id']); + + $rules = $this->listRules([ + 'search' => $rule1Domain, + 'queries' => [ Query::orderDesc('$createdAt') ] + ]); + + $this->assertEquals(200, $rules['headers']['status-code']); + $ruleIds = \array_column($rules['body']['rules'], '$id'); + $this->assertContains($rule1Id, $ruleIds); + + $rules = $this->listRules([ + 'search' => $rule2Domain, + 'queries' => [ Query::orderDesc('$createdAt') ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $ruleIds = \array_column($rules['body']['rules'], '$id'); + $this->assertContains($rule2Id, $ruleIds); + + $rules = $this->listRules([ + 'search' => $rule1Id, + 'queries' => [ Query::orderDesc('$createdAt') ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $ruleDomains = \array_column($rules['body']['rules'], 'domain'); + $this->assertContains($rule1Domain, $ruleDomains); + + $rules = $this->listRules([ + 'search' => $rule2Id, + 'queries' => [ Query::orderDesc('$createdAt') ] + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $ruleDomains = \array_column($rules['body']['rules'], 'domain'); + $this->assertContains($rule2Domain, $ruleDomains); + + $rules = $this->listRules(); + $this->assertEquals(200, $rules['headers']['status-code']); + foreach ($rules['body']['rules'] as $rule) { + $rule = $this->deleteRule($rule['$id']); + $this->assertEquals(204, $rule['headers']['status-code']); + } + + $rules = $this->listRules(); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(0, $rules['body']['total']); + $this->assertCount(0, $rules['body']['rules']); + } +} diff --git a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php index 0155d251f2..4e27457b05 100644 --- a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php @@ -534,10 +534,11 @@ class RealtimeConsoleClientTest extends Scope 'timeout' => 10 ]); - $functionId = $response1['body']['$id'] ?? ''; - $this->assertEquals(201, $response1['headers']['status-code']); + $functionId = $response1['body']['$id']; + $this->assertNotEmpty($functionId); + $projectId = 'console'; $client = $this->getWebsocket(['console'], [ @@ -570,6 +571,9 @@ class RealtimeConsoleClientTest extends Scope $this->assertEquals(202, $deployment['headers']['status-code']); + $deploymentId = $deployment['body']['$id']; + $this->assertNotEmpty($deploymentId); + $response = json_decode($client->receive(), true); $this->assertArrayHasKey('type', $response); @@ -580,8 +584,55 @@ class RealtimeConsoleClientTest extends Scope $this->assertCount(2, $response['data']['channels']); $this->assertContains('console', $response['data']['channels']); $this->assertContains("projects.{$projectId}", $response['data']['channels']); - // $this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.create", $response['data']['events']); TODO @christyjacob4 : enable test once we allow functions.* events - $this->assertNotEmpty($response['data']['payload']); + $this->assertEquals("waiting", $response['data']['payload']['status']); + $this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.create", $response['data']['events']); + + $response = json_decode($client->receive(), true); + $this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.update", $response['data']['events']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertEquals("processing", $response['data']['payload']['status']); + + $response = json_decode($client->receive(), true); + $this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.update", $response['data']['events']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertEquals("building", $response['data']['payload']['status']); + + $previousBuildLogs = null; + while (true) { + $response = json_decode($client->receive(), true); + $this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.update", $response['data']['events']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertArrayHasKey('buildLogs', $response['data']['payload']); + + // Ignore comparasion for first payload + if ($previousBuildLogs !== null) { + $this->assertNotEquals($previousBuildLogs, $response['data']['payload']['buildLogs']); + } + + $previousBuildLogs = $response['data']['payload']['buildLogs']; + + $this->assertEquals('building', $response['data']['payload']['status']); + + if (!empty($response['data']['payload']['buildEndAt'])) { + $this->assertNotEmpty($response['data']['payload']['buildEndAt']); + $this->assertNotEmpty($response['data']['payload']['buildStartAt']); + $this->assertNotEmpty($response['data']['payload']['buildDuration']); + $this->assertNotEmpty($response['data']['payload']['buildPath']); + $this->assertNotEmpty($response['data']['payload']['buildSize']); + $this->assertNotEmpty($response['data']['payload']['totalSize']); + $this->assertNotEmpty($response['data']['payload']['buildLogs']); + break; + } + } + + $response = json_decode($client->receive(), true); + $this->assertContains("functions.{$functionId}.deployments.{$deploymentId}.update", $response['data']['events']); + $this->assertContains('console', $response['data']['channels']); + $this->assertContains("projects.{$projectId}", $response['data']['channels']); + $this->assertEquals("ready", $response['data']['payload']['status']); $client->close(); } diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index dda524fc7c..e356397408 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -1312,22 +1312,15 @@ class RealtimeCustomClientTest extends Scope $this->assertNotEmpty($deployment['body']['$id']); // Poll until deployment is built - while (true) { + $this->assertEventually(function () use ($function, $deploymentId) { $deployment = $this->client->call(Client::METHOD_GET, '/functions/' . $function['body']['$id'] . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]); - if ( - $deployment['headers']['status-code'] >= 400 - || \in_array($deployment['body']['status'], ['ready', 'failed']) - ) { - break; - } - - \sleep(1); - } + $this->assertEquals('ready', $deployment['body']['status'], \json_encode($deployment['body'])); + }); $response = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployments/' . $deploymentId, array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Sites/SitesBase.php b/tests/e2e/Services/Sites/SitesBase.php new file mode 100644 index 0000000000..00edcc1b72 --- /dev/null +++ b/tests/e2e/Services/Sites/SitesBase.php @@ -0,0 +1,437 @@ +<?php + +namespace Tests\E2E\Services\Sites; + +use Appwrite\Tests\Async; +use CURLFile; +use Tests\E2E\Client; +use Utopia\CLI\Console; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Query; +use Utopia\System\System; + +trait SitesBase +{ + use Async; + + protected string $stdout = ''; + protected string $stderr = ''; + + protected function setupSite(mixed $params): string + { + $site = $this->client->call(Client::METHOD_POST, '/sites', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), $params); + + $this->assertEquals($site['headers']['status-code'], 201, 'Setup site failed with status code: ' . $site['headers']['status-code'] . ' and response: ' . json_encode($site['body'], JSON_PRETTY_PRINT)); + + $siteId = $site['body']['$id']; + + return $siteId; + } + + protected function setupDeployment(string $siteId, mixed $params): string + { + $deployment = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), $params); + $this->assertEquals($deployment['headers']['status-code'], 202, 'Setup deployment failed with status code: ' . $deployment['headers']['status-code'] . ' and response: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + $deploymentId = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($siteId, $deploymentId) { + $deployment = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + '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)); + }, 150000, 500); + + // Not === so multipart/form-data works fine too + if (($params['activate'] ?? false) == true) { + $this->assertEventually(function () use ($siteId, $deploymentId) { + $site = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertEquals($deploymentId, $site['body']['deploymentId'], 'Deployment is not activated, deployment: ' . json_encode($site['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + } + + return $deploymentId; + } + + protected function cleanupSite(string $siteId): void + { + $site = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + + $this->assertEquals($site['headers']['status-code'], 204); + } + + protected function cleanupDeployment(string $siteId, string $deploymentId): void + { + $deployment = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + + $this->assertEquals($deployment['headers']['status-code'], 204); + } + + protected function createSite(mixed $params): mixed + { + $site = $this->client->call(Client::METHOD_POST, '/sites', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $site; + } + + protected function updateSite(mixed $params): mixed + { + $site = $this->client->call(Client::METHOD_PUT, '/sites/' . $params['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $site; + } + + protected function createVariable(string $siteId, mixed $params): mixed + { + $variable = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/variables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $variable; + } + + protected function getVariable(string $siteId, string $variableId): mixed + { + $variable = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/variables/' . $variableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $variable; + } + + protected function listVariables(string $siteId, mixed $params = []): mixed + { + $variables = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/variables', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $variables; + } + + protected function updateVariable(string $siteId, string $variableId, mixed $params): mixed + { + $variable = $this->client->call(Client::METHOD_PUT, '/sites/' . $siteId . '/variables/' . $variableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $variable; + } + + protected function deleteVariable(string $siteId, string $variableId): mixed + { + $variable = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId . '/variables/' . $variableId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $variable; + } + + protected function getSite(string $siteId): mixed + { + $site = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $site; + } + + protected function getDeployment(string $siteId, string $deploymentId): mixed + { + $deployment = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $deployment; + } + + protected function getLog(string $siteId, $logId): mixed + { + $log = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/logs/' . $logId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $log; + } + + protected function listSites(mixed $params = []): mixed + { + $sites = $this->client->call(Client::METHOD_GET, '/sites', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $sites; + } + + protected function listDeployments(string $siteId, $params = []): mixed + { + $deployments = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/deployments', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $deployments; + } + + protected function listLogs(string $siteId, array $queries = []): mixed + { + $logs = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/logs', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => $queries + ]); + + return $logs; + } + + protected function packageSite(string $site): CURLFile + { + $folderPath = realpath(__DIR__ . '/../../../resources/sites') . "/$site"; + $tarPath = "$folderPath/code.tar.gz"; + + Console::execute("cd $folderPath && tar --exclude code.tar.gz -czf code.tar.gz .", '', $this->stdout, $this->stderr); + + if (filesize($tarPath) > 1024 * 1024 * 5) { + throw new \Exception('Code package is too large. Use the chunked upload method instead.'); + } + + return new CURLFile($tarPath, 'application/x-gzip', \basename($tarPath)); + } + + protected function createDeployment(string $siteId, mixed $params = []): mixed + { + $deployment = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $deployment; + } + + protected function deleteDeployment(string $siteId, string $deploymentId): mixed + { + $deployment = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + return $deployment; + } + + protected function setupDuplicateDeployment(string $siteId, string $deploymentId): string + { + $deployment = $this->createDuplicateDeployment($siteId, $deploymentId); + $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('ready', $deployment['body']['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + $this->assertEventually(function () use ($siteId, $deploymentId) { + $site = $this->getSite($siteId); + $this->assertEquals($deploymentId, $site['body']['deploymentId'], 'Deployment is not activated, deployment: ' . json_encode($site['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + return $deploymentId; + } + + protected function createDuplicateDeployment(string $siteId, string $deploymentId): mixed + { + $deployment = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments/duplicate', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'deploymentId' => $deploymentId, + ]); + + return $deployment; + } + + protected function createTemplateDeployment(string $siteId, mixed $params = []): mixed + { + $deployment = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments/template', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $deployment; + } + + protected function getUsage(string $siteId, mixed $params): mixed + { + $usage = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/usage', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + + return $usage; + } + + protected function getTemplate(string $templateId) + { + $template = $this->client->call(Client::METHOD_GET, '/sites/templates/' . $templateId, [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]); + return $template; + } + + protected function deleteSite(string $siteId): mixed + { + $site = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $site; + } + + protected function setupSiteDomain(string $siteId, string $subdomain = ''): string + { + $subdomain = $subdomain ? $subdomain : ID::unique(); + $rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/site', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'domain' => $subdomain . '.' . System::getEnv('_APP_DOMAIN_SITES', ''), + 'siteId' => $siteId, + ]); + + $this->assertEquals(201, $rule['headers']['status-code']); + $this->assertNotEmpty($rule['body']['$id']); + $this->assertNotEmpty($rule['body']['domain']); + + $domain = $rule['body']['domain']; + + return $domain; + } + + protected function getSiteDomain(string $siteId): string + { + $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('deploymentResourceId', [$siteId])->toString(), + Query::equal('trigger', ['manual'])->toString(), + Query::equal('type', ['deployment'])->toString(), + ], + ]); + + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertGreaterThanOrEqual(1, $rules['body']['total']); + $this->assertGreaterThanOrEqual(1, \count($rules['body']['rules'])); + $this->assertNotEmpty($rules['body']['rules'][0]['domain']); + + $domain = $rules['body']['rules'][0]['domain']; + + return $domain; + } + + protected function getDeploymentDomain(string $deploymentId): string + { + $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('deploymentId', [$deploymentId])->toString(), + Query::equal('type', ['deployment'])->toString(), + Query::equal('trigger', ['deployment'])->toString(), + ], + ]); + + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertGreaterThanOrEqual(1, $rules['body']['total']); + $this->assertGreaterThanOrEqual(1, \count($rules['body']['rules'])); + $this->assertNotEmpty($rules['body']['rules'][0]['domain']); + + $domain = $rules['body']['rules'][0]['domain']; + + return $domain; + } + + protected function getDeploymentDownload(string $siteId, string $deploymentId, string $type): mixed + { + $response = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/deployments/' . $deploymentId . '/download', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'type' => $type, + ]); + + return $response; + } + + protected function updateSiteDeployment(string $siteId, string $deploymentId): mixed + { + $site = $this->client->call(Client::METHOD_PATCH, '/sites/' . $siteId . '/deployment', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'deploymentId' => $deploymentId + ]); + + return $site; + } + + protected function cancelDeployment(string $siteId, string $deploymentId): mixed + { + $deployment = $this->client->call(Client::METHOD_PATCH, '/sites/' . $siteId . '/deployments/' . $deploymentId . '/status', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $deployment; + } + + protected function listSpecifications(): mixed + { + $specifications = $this->client->call(Client::METHOD_GET, '/sites/specifications', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + return $specifications; + } +} diff --git a/tests/e2e/Services/Sites/SitesCustomClientTest.php b/tests/e2e/Services/Sites/SitesCustomClientTest.php new file mode 100644 index 0000000000..9bf389ea62 --- /dev/null +++ b/tests/e2e/Services/Sites/SitesCustomClientTest.php @@ -0,0 +1,141 @@ +<?php + +namespace Tests\E2E\Services\Sites; + +use Tests\E2E\Client; +use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\SideClient; + +class SitesCustomClientTest extends Scope +{ + use SitesBase; + use ProjectCustom; + use SideClient; + + public function testListTemplates() + { + /** + * Test for SUCCESS + */ + // List all templates + $templates = $this->client->call(Client::METHOD_GET, '/sites/templates', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $templates['headers']['status-code']); + $this->assertGreaterThan(0, $templates['body']['total']); + $this->assertIsArray($templates['body']['templates']); + + foreach ($templates['body']['templates'] as $template) { + $this->assertArrayHasKey('name', $template); + $this->assertArrayHasKey('key', $template); + $this->assertArrayHasKey('useCases', $template); + $this->assertArrayHasKey('vcsProvider', $template); + $this->assertArrayHasKey('frameworks', $template); + $this->assertArrayHasKey('variables', $template); + $this->assertArrayHasKey('screenshotDark', $template); + $this->assertArrayHasKey('screenshotLight', $template); + $this->assertArrayHasKey('tagline', $template); + } + + // List templates with pagination + $templatesOffset = $this->client->call(Client::METHOD_GET, '/sites/templates', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'limit' => 1, + 'offset' => 2 + ]); + $this->assertEquals(200, $templatesOffset['headers']['status-code']); + $this->assertCount(1, $templatesOffset['body']['templates']); + $this->assertEquals($templates['body']['templates'][2]['key'], $templatesOffset['body']['templates'][0]['key']); + + // List templates with filters + $templates = $this->client->call(Client::METHOD_GET, '/sites/templates', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'useCases' => ['starter'], + 'frameworks' => ['nuxt'] + ]); + $this->assertEquals(200, $templates['headers']['status-code']); + $this->assertGreaterThan(0, $templates['body']['total']); + $this->assertIsArray($templates['body']['templates']); + foreach ($templates['body']['templates'] as $template) { + $this->assertContains($template['useCases'][0], ['starter']); + } + $this->assertArrayHasKey('frameworks', $templates['body']['templates'][0]); + $this->assertContains('Nuxt', array_column($templates['body']['templates'][0]['frameworks'], 'name')); + + // List templates with pagination and filters + $templates = $this->client->call(Client::METHOD_GET, '/sites/templates', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'limit' => 5, + 'offset' => 0, + 'useCases' => ['starter'], + 'frameworks' => ['nextjs'] + ]); + + $this->assertEquals(200, $templates['headers']['status-code']); + $this->assertGreaterThan(0, $templates['body']['total']); + $this->assertIsArray($templates['body']['templates']); + $this->assertArrayHasKey('frameworks', $templates['body']['templates'][0]); + + foreach ($templates['body']['templates'] as $template) { + $this->assertContains($template['useCases'][0], ['starter']); + } + + $this->assertContains('Next.js', array_column($templates['body']['templates'][0]['frameworks'], 'name')); + + /** + * Test for FAILURE + */ + // List templates with invalid limit + $templates = $this->client->call(Client::METHOD_GET, '/sites/templates', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'limit' => 5001, + 'offset' => 10, + ]); + $this->assertEquals(400, $templates['headers']['status-code']); + + // List templates with invalid offset + $templates = $this->client->call(Client::METHOD_GET, '/sites/templates', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'limit' => 5, + 'offset' => 5001, + ]); + $this->assertEquals(400, $templates['headers']['status-code']); + } + + public function testGetTemplate() + { + /** + * Test for SUCCESS + */ + $template = $this->getTemplate('starter-for-react'); + $this->assertEquals(200, $template['headers']['status-code']); + $this->assertIsArray($template['body']); + $this->assertEquals('starter-for-react', $template['body']['key']); + $this->assertEquals('React starter', $template['body']['name']); + $this->assertEquals(['starter'], $template['body']['useCases']); + $this->assertEquals('github', $template['body']['vcsProvider']); + $this->assertEquals('Simple React application integrated with Appwrite SDK.', $template['body']['tagline']); + $this->assertIsArray($template['body']['frameworks']); + $this->assertEquals('http://localhost/images/sites/templates/starter-for-react-dark.png', $template['body']['screenshotDark']); + $this->assertEquals('http://localhost/images/sites/templates/starter-for-react-light.png', $template['body']['screenshotLight']); + + /** + * Test for FAILURE + */ + $template = $this->getTemplate('invalid-template-id'); + $this->assertEquals(404, $template['headers']['status-code']); + } +} diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php new file mode 100644 index 0000000000..1775995216 --- /dev/null +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -0,0 +1,2710 @@ +<?php + +namespace Tests\E2E\Services\Sites; + +use Ahc\Jwt\JWT; +use Appwrite\Platform\Modules\Compute\Specification; +use Appwrite\Tests\Retry; +use Tests\E2E\Client; +use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Scopes\Scope; +use Tests\E2E\Scopes\SideServer; +use Utopia\CLI\Console; +use Utopia\Database\Document; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Query; +use Utopia\Database\Validator\Datetime as DatetimeValidator; +use Utopia\System\System; + +class SitesCustomServerTest extends Scope +{ + use SitesBase; + use ProjectCustom; + use SideServer; + + public function testListSpecs(): void + { + $specifications = $this->listSpecifications(); + $this->assertEquals(200, $specifications['headers']['status-code']); + $this->assertGreaterThan(0, $specifications['body']['total']); + $this->assertArrayHasKey(0, $specifications['body']['specifications']); + $this->assertArrayHasKey('memory', $specifications['body']['specifications'][0]); + $this->assertArrayHasKey('cpus', $specifications['body']['specifications'][0]); + $this->assertArrayHasKey('enabled', $specifications['body']['specifications'][0]); + $this->assertArrayHasKey('slug', $specifications['body']['specifications'][0]); + + $site = $this->createSite([ + 'buildRuntime' => 'node-22', + 'framework' => 'other', + 'name' => 'Specs site', + 'siteId' => ID::unique(), + 'specification' => $specifications['body']['specifications'][0]['slug'] + ]); + $this->assertEquals(201, $site['headers']['status-code']); + $this->assertEquals($specifications['body']['specifications'][0]['slug'], $site['body']['specification']); + + $site = $this->getSite($site['body']['$id']); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($specifications['body']['specifications'][0]['slug'], $site['body']['specification']); + + $this->cleanupSite($site['body']['$id']); + + $site = $this->createSite([ + 'buildRuntime' => 'node-22', + 'framework' => 'other', + 'name' => 'Specs site', + 'siteId' => ID::unique(), + 'specification' => 'cheap-please' + ]); + $this->assertEquals(400, $site['headers']['status-code']); + } + + public function testCreateSite(): void + { + /** + * Test for SUCCESS + */ + $site = $this->createSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'siteId' => ID::unique() + ]); + + $siteId = $site['body']['$id'] ?? ''; + + $dateValidator = new DateTimeValidator(); + $this->assertEquals(201, $site['headers']['status-code']); + $this->assertNotEmpty($site['body']['$id']); + $this->assertEquals('Test Site', $site['body']['name']); + $this->assertEquals('other', $site['body']['framework']); + $this->assertEquals(true, $dateValidator->isValid($site['body']['$createdAt'])); + $this->assertEquals(true, $dateValidator->isValid($site['body']['$updatedAt'])); + $this->assertEquals('node-22', $site['body']['buildRuntime']); + $this->assertEquals(null, $site['body']['fallbackFile']); + $this->assertEquals('./', $site['body']['outputDirectory']); + + $variable = $this->createVariable($siteId, [ + 'key' => 'siteKey1', + 'value' => 'siteValue1', + ]); + $variable2 = $this->createVariable($siteId, [ + 'key' => 'siteKey2', + 'value' => 'siteValue2', + ]); + $variable3 = $this->createVariable($siteId, [ + 'key' => 'siteKey3', + 'value' => 'siteValue3', + ]); + + $this->assertEquals(201, $variable['headers']['status-code']); + $this->assertEquals(201, $variable2['headers']['status-code']); + $this->assertEquals(201, $variable3['headers']['status-code']); + + $this->cleanupSite($siteId); + } + + public function testConsoleAvailabilityEndpoint(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Test Site', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './', + 'fallbackFile' => '', + ]); + + $this->assertNotEmpty($siteId); + + $domain = $this->setupSiteDomain($siteId); + + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-project' => 'console', + ], [ + 'type' => 'rules', + 'value' => $domain, + ]); + + $this->assertEquals(409, $response['headers']['status-code']); // domain unavailable + + $nonExistingDomain = "non-existent-subdomain.sites.localhost"; + + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-project' => 'console', + ], [ + 'type' => 'rules', + 'value' => $nonExistingDomain, + ]); + + $this->assertEquals(204, $response['headers']['status-code']); // domain available + + $this->cleanupSite($siteId); + + $this->assertEventually(function () use ($siteId) { + $rule = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('deploymentResourceId', [$siteId]) + ] + ]); + + $this->assertEquals(200, $rule['headers']['status-code']); + $this->assertEquals(0, $rule['body']['total']); + }, 5000, 500); + + $response = $this->client->call(Client::METHOD_GET, '/console/resources', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + 'x-appwrite-project' => 'console', + ], [ + 'type' => 'rules', + 'value' => $domain, + ]); + + $this->assertEquals(204, $response['headers']['status-code']); // domain available as site is deleted + } + + public function testVariables(): void + { + $site = $this->createSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'siteId' => ID::unique() + ]); + + $siteId = $site['body']['$id'] ?? ''; + + $this->assertEquals(201, $site['headers']['status-code']); + $this->assertNotEmpty($site['body']['$id']); + $this->assertEquals('Test Site', $site['body']['name']); + + $variable = $this->createVariable($siteId, [ + 'key' => 'siteKey1', + 'value' => 'siteValue1', + 'secret' => false, + ]); + + $this->assertEquals(201, $variable['headers']['status-code']); + $this->assertNotEmpty($variable['body']['$id']); + $this->assertEquals('siteKey1', $variable['body']['key']); + $this->assertEquals('siteValue1', $variable['body']['value']); + $this->assertEquals(false, $variable['body']['secret']); + + $variable2 = $this->createVariable($siteId, [ + 'key' => 'siteKey2', + 'value' => 'siteValue2', + 'secret' => false, + ]); + + $this->assertEquals(201, $variable2['headers']['status-code']); + $this->assertNotEmpty($variable2['body']['$id']); + $this->assertEquals('siteKey2', $variable2['body']['key']); + $this->assertEquals('siteValue2', $variable2['body']['value']); + $this->assertEquals(false, $variable2['body']['secret']); + + $secretVariable = $this->createVariable($siteId, [ + 'key' => 'siteKey3', + 'value' => 'siteValue3', + 'secret' => true, + ]); + + $this->assertEquals(201, $secretVariable['headers']['status-code']); + $this->assertNotEmpty($secretVariable['body']['$id']); + $this->assertEquals('siteKey3', $secretVariable['body']['key']); + $this->assertEquals('', $secretVariable['body']['value']); + $this->assertEquals(true, $secretVariable['body']['secret']); + + $variable = $this->getVariable($siteId, $variable['body']['$id']); + + $this->assertEquals(200, $variable['headers']['status-code']); + $this->assertNotEmpty($variable['body']['$id']); + $this->assertEquals('siteKey1', $variable['body']['key']); + $this->assertEquals('siteValue1', $variable['body']['value']); + $this->assertEquals(false, $variable['body']['secret']); + + $secretVariable = $this->getVariable($siteId, $secretVariable['body']['$id']); + + $this->assertEquals(200, $secretVariable['headers']['status-code']); + $this->assertNotEmpty($secretVariable['body']['$id']); + $this->assertEquals('siteKey3', $secretVariable['body']['key']); + $this->assertEquals('', $secretVariable['body']['value']); + $this->assertEquals(true, $secretVariable['body']['secret']); + + $variable = $this->updateVariable($siteId, $variable['body']['$id'], [ + 'key' => 'siteKey1Updated', + 'value' => 'siteValue1Updated', + ]); + + $this->assertEquals(200, $variable['headers']['status-code']); + $this->assertNotEmpty($variable['body']['$id']); + $this->assertEquals('siteKey1Updated', $variable['body']['key']); + $this->assertEquals('siteValue1Updated', $variable['body']['value']); + $this->assertEquals(false, $variable['body']['secret']); + + $variable = $this->updateVariable($siteId, $variable['body']['$id'], [ + 'key' => 'siteKey1Updated', + 'secret' => true, + ]); + + $this->assertEquals(200, $variable['headers']['status-code']); + $this->assertNotEmpty($variable['body']['$id']); + $this->assertEquals('siteKey1Updated', $variable['body']['key']); + $this->assertEquals('', $variable['body']['value']); + $this->assertEquals(true, $variable['body']['secret']); + + $secretVariable = $this->updateVariable($siteId, $secretVariable['body']['$id'], [ + 'key' => 'siteKey3', + 'value' => 'siteValue3Updated', + ]); + + $this->assertEquals(200, $secretVariable['headers']['status-code']); + $this->assertNotEmpty($secretVariable['body']['$id']); + $this->assertEquals('siteKey3', $secretVariable['body']['key']); + $this->assertEquals('', $secretVariable['body']['value']); + $this->assertEquals(true, $secretVariable['body']['secret']); + + $response = $this->updateVariable($siteId, $secretVariable['body']['$id'], [ + 'key' => 'siteKey3', + 'secret' => false, + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + $secretVariable = $this->getVariable($siteId, $secretVariable['body']['$id']); + + $this->assertEquals(200, $secretVariable['headers']['status-code']); + $this->assertNotEmpty($secretVariable['body']['$id']); + $this->assertEquals('siteKey3', $secretVariable['body']['key']); + $this->assertEquals('', $secretVariable['body']['value']); + $this->assertEquals(true, $secretVariable['body']['secret']); + + $variables = $this->listVariables($siteId); + + $this->assertEquals(200, $variables['headers']['status-code']); + $this->assertCount(3, $variables['body']['variables']); + + $response = $this->deleteVariable($siteId, $variable['body']['$id']); + $this->assertEquals(204, $response['headers']['status-code']); + $response = $this->deleteVariable($siteId, $variable2['body']['$id']); + $this->assertEquals(204, $response['headers']['status-code']); + $response = $this->deleteVariable($siteId, $secretVariable['body']['$id']); + $this->assertEquals(204, $response['headers']['status-code']); + + $variables = $this->listVariables($siteId); + + $this->assertEquals(200, $variables['headers']['status-code']); + $this->assertCount(0, $variables['body']['variables']); + + $this->cleanupSite($siteId); + } + + // This is first Sites test with Proxy + // If this fails, it may not be related to variables; but Router flow failing + public function testVariablesE2E(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Astro site', + 'framework' => 'astro', + 'adapter' => 'ssr', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './dist', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'fallbackFile' => '', + ]); + + $this->assertNotEmpty($siteId); + + $domain = $this->setupSiteDomain($siteId); + + $secretVariable = $this->createVariable($siteId, [ + 'key' => 'name', + 'value' => 'Appwrite', + ]); + + $this->assertEquals(201, $secretVariable['headers']['status-code']); + $this->assertNotEmpty($secretVariable['body']['$id']); + $this->assertEquals('name', $secretVariable['body']['key']); + $this->assertEquals('', $secretVariable['body']['value']); + $this->assertEquals(true, $secretVariable['body']['secret']); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('astro'), + 'activate' => 'true' + ]); + + $this->assertNotEmpty($deploymentId); + + $domain = $this->getSiteDomain($siteId); + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Env variable is Appwrite", $response['body']); + $this->assertStringNotContainsString("Variable not found", $response['body']); + + $deployment = $this->getDeployment($siteId, $deploymentId); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertGreaterThan(0, $deployment['body']['sourceSize']); + $this->assertGreaterThan(0, $deployment['body']['buildSize']); + $totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize']; + $this->assertEquals($totalSize, $deployment['body']['totalSize']); + + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertNotEmpty($site['body']['deploymentId']); + $this->assertNotEmpty($site['body']['deploymentCreatedAt']); + $this->assertEquals($deployment['body']['$id'], $site['body']['deploymentId']); + $this->assertEquals($deployment['body']['$createdAt'], $site['body']['deploymentCreatedAt']); + + $this->cleanupSite($siteId); + } + + public function testAdapterDetectionAstroSSR(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Astro SSR site', + 'framework' => 'astro', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './dist', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + ]); + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertArrayHasKey('adapter', $site['body']); + $this->assertEmpty($site['body']['adapter']); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('astro'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId); + + $site = $this->getSite($siteId); + $this->assertEquals('ssr', $site['body']['adapter']); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + + $this->cleanupSite($siteId); + } + + public function testAdapterDetectionAstroStatic(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Astro static site', + 'framework' => 'astro', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './dist', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + ]); + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertArrayHasKey('adapter', $site['body']); + $this->assertEmpty($site['body']['adapter']); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('astro-static'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertEquals('static', $site['body']['adapter']); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + + $this->cleanupSite($siteId); + } + + public function testAdapterDetectionStatic(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Static site', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => '', + 'buildCommand' => '', + 'installCommand' => '', + ]); + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertArrayHasKey('adapter', $site['body']); + $this->assertEmpty($site['body']['adapter']); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertEquals('static', $site['body']['adapter']); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + + $this->cleanupSite($siteId); + } + + public function testAdapterDetectionStaticSPA(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Static site', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => '', + 'buildCommand' => '', + 'installCommand' => '', + ]); + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertArrayHasKey('adapter', $site['body']); + $this->assertArrayHasKey('fallbackFile', $site['body']); + $this->assertEmpty($site['body']['adapter']); + $this->assertEmpty($site['body']['fallbackFile']); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static-single-file'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertEquals('static', $site['body']['adapter']); + $this->assertEquals('main.html', $site['body']['fallbackFile']); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString('Main page', $response['body']); + $response = $proxyClient->call(Client::METHOD_GET, '/something'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString('Main page', $response['body']); + + $this->cleanupSite($siteId); + } + + public function testSettingsForRollback(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Static site', + 'framework' => 'astro', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './dist', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + ]); + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertEmpty($site['body']['adapter']); + $this->assertEmpty($site['body']['fallbackFile']); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $deploymentId1 = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('astro-static'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId1); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertEquals('static', $site['body']['adapter']); + $this->assertEquals('index.html', $site['body']['fallbackFile']); + + $site = $this->updateSite([ + 'name' => 'SSR site', + 'framework' => 'astro', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './dist', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'adapter' => 'ssr', + 'fallbackFile' => '', + '$id' => $siteId, + ]); + + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertEquals('ssr', $site['body']['adapter']); + $this->assertEmpty($site['body']['fallbackFile']); + + $deploymentId2 = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('astro'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId2); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + $this->assertEquals('ssr', $site['body']['adapter']); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Astro SSR", $response['body']); + $response = $proxyClient->call(Client::METHOD_GET, '/not-found'); + $this->assertEquals(404, $response['headers']['status-code']); + + $response = $this->updateSiteDeployment($siteId, $deploymentId1); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Astro static", $response['body']); + $response = $proxyClient->call(Client::METHOD_GET, '/not-found'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Astro static", $response['body']); + + $this->cleanupSite($siteId); + } + + public function testListSites(): void + { + /** + * Test for SUCCESS + */ + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $sites = $this->listSites([ + 'search' => $siteId, + ]); + + $this->assertEquals($sites['headers']['status-code'], 200); + $this->assertCount(1, $sites['body']['sites']); + $this->assertEquals($sites['body']['sites'][0]['name'], 'Test Site'); + + // Test pagination limit + $sites = $this->listSites([ + 'queries' => [ + Query::limit(1)->toString(), + ], + ]); + + $this->assertEquals($sites['headers']['status-code'], 200); + $this->assertCount(1, $sites['body']['sites']); + + // Test pagination offset + $sites = $this->listSites([ + 'queries' => [ + Query::offset(1)->toString(), + ], + ]); + + $this->assertEquals($sites['headers']['status-code'], 200); + $this->assertCount(0, $sites['body']['sites']); + + // Test filter enabled + $sites = $this->listSites([ + 'queries' => [ + Query::equal('enabled', [true])->toString(), + ], + ]); + + $this->assertEquals($sites['headers']['status-code'], 200); + $this->assertCount(1, $sites['body']['sites']); + + // Test filter disabled + $sites = $this->listSites([ + 'queries' => [ + Query::equal('enabled', [false])->toString(), + ], + ]); + + $this->assertEquals($sites['headers']['status-code'], 200); + $this->assertCount(0, $sites['body']['sites']); + + // Test search name + $sites = $this->listSites([ + 'search' => 'Test' + ]); + + $this->assertEquals($sites['headers']['status-code'], 200); + $this->assertCount(1, $sites['body']['sites']); + $this->assertEquals($sites['body']['sites'][0]['$id'], $siteId); + + // Test search framework + $sites = $this->listSites([ + 'search' => 'other' + ]); + + $this->assertEquals($sites['headers']['status-code'], 200); + $this->assertCount(1, $sites['body']['sites']); + $this->assertEquals($sites['body']['sites'][0]['$id'], $siteId); + + /** + * Test pagination + */ + $siteId2 = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site 2', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $sites = $this->listSites(); + + $this->assertEquals($sites['headers']['status-code'], 200); + $this->assertEquals($sites['body']['total'], 2); + $this->assertIsArray($sites['body']['sites']); + $this->assertCount(2, $sites['body']['sites']); + $this->assertEquals($sites['body']['sites'][0]['name'], 'Test Site'); + $this->assertEquals($sites['body']['sites'][1]['name'], 'Test Site 2'); + + $sites1 = $this->listSites([ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => $sites['body']['sites'][0]['$id']]))->toString(), + ], + ]); + + $this->assertEquals($sites1['headers']['status-code'], 200); + $this->assertCount(1, $sites1['body']['sites']); + $this->assertEquals($sites1['body']['sites'][0]['name'], 'Test Site 2'); + + $sites2 = $this->listSites([ + 'queries' => [ + Query::cursorBefore(new Document(['$id' => $sites['body']['sites'][1]['$id']]))->toString(), + ], + ]); + + $this->assertEquals($sites2['headers']['status-code'], 200); + $this->assertCount(1, $sites2['body']['sites']); + $this->assertEquals($sites2['body']['sites'][0]['name'], 'Test Site'); + + /** + * Test for FAILURE + */ + $sites = $this->listSites([ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => 'unknown']))->toString(), + ], + ]); + $this->assertEquals($sites['headers']['status-code'], 400); + + $this->cleanupSite($siteId); + $this->cleanupSite($siteId2); + } + + public function testGetSite(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + /** + * Test for SUCCESS + */ + $site = $this->getSite($siteId); + + $this->assertEquals($site['headers']['status-code'], 200); + $this->assertEquals($site['body']['name'], 'Test Site'); + + /** + * Test for FAILURE + */ + $site = $this->getSite('x'); + + $this->assertEquals($site['headers']['status-code'], 404); + + $this->cleanupSite($siteId); + } + + public function testUpdateSite(): void + { + $site = $this->createSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $siteId = $site['body']['$id'] ?? ''; + + $this->assertEquals(201, $site['headers']['status-code']); + $this->assertNotEmpty($site['body']['$id']); + $this->assertEquals('Test Site', $site['body']['name']); + + $site = $this->updateSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site Updated', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + '$id' => $siteId, + 'installCommand' => 'npm install' + ]); + + $dateValidator = new DatetimeValidator(); + + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertNotEmpty($site['body']['$id']); + $this->assertEquals('Test Site Updated', $site['body']['name']); + $this->assertEquals(true, $dateValidator->isValid($site['body']['$createdAt'])); + $this->assertEquals(true, $dateValidator->isValid($site['body']['$updatedAt'])); + $this->assertEquals('npm install', $site['body']['installCommand']); + + $this->cleanupSite($siteId); + } + + // public function testCreateDeploymentFromCLI() { + // // TODO: Implement testCreateDeploymentFromCLI() later + // } + + public function testCreateDeployment() + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + $deployment = $this->createDeployment($siteId, [ + 'siteId' => $siteId, + 'code' => $this->packageSite('static'), + 'activate' => true, + ]); + + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + $this->assertEquals('waiting', $deployment['body']['status']); + $this->assertEquals(true, (new DatetimeValidator())->isValid($deployment['body']['$createdAt'])); + + $deploymentIdActive = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($siteId, $deploymentIdActive) { + $deployment = $this->getDeployment($siteId, $deploymentIdActive); + + $this->assertEquals('ready', $deployment['body']['status']); + }, 50000, 500); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'false' + ]); + + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + + $deploymentIdInactive = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($siteId, $deploymentIdInactive) { + $deployment = $this->getDeployment($siteId, $deploymentIdInactive); + + $this->assertEquals('ready', $deployment['body']['status']); + }, 50000, 500); + + $site = $this->getSite($siteId); + + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentIdActive, $site['body']['deploymentId']); + $this->assertNotEquals($deploymentIdInactive, $site['body']['deploymentId']); + + $this->cleanupDeployment($siteId, $deploymentIdActive); + $this->cleanupDeployment($siteId, $deploymentIdInactive); + $this->cleanupSite($siteId); + } + + #[Retry(count: 3)] + public function testCancelDeploymentBuild(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'false' + ]); + + $deploymentId = $deployment['body']['$id'] ?? ''; + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + $this->assertEquals(true, (new DatetimeValidator())->isValid($deployment['body']['$createdAt'])); + + $this->assertEventually(function () use ($siteId, $deploymentId) { + $deployment = $this->getDeployment($siteId, $deploymentId); + + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertEquals('building', $deployment['body']['status']); + }, 100000, 250); + + $deployment = $this->cancelDeployment($siteId, $deploymentId); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertEquals('canceled', $deployment['body']['status']); + + /** + * Build worker still runs the build. + * 30s sleep gives worker enough time to finish build. + * After build finished, it should still be canceled, not ready. + */ + \sleep(30); + + $deployment = $this->getDeployment($siteId, $deploymentId); + + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertEquals('canceled', $deployment['body']['status']); + + $this->cleanupDeployment($siteId, $deploymentId); + $this->cleanupSite($siteId); + } + + public function testUpdateDeployment(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'false' + ]); + + $deploymentId = $deployment['body']['$id'] ?? ''; + $this->assertEquals(202, $deployment['headers']['status-code']); + + $this->assertEventually(function () use ($siteId, $deploymentId) { + $deployment = $this->getDeployment($siteId, $deploymentId); + + $this->assertEquals('ready', $deployment['body']['status']); + }, 50000, 500); + + /** + * Test for SUCCESS + */ + $dateValidator = new DatetimeValidator(); + + $response = $this->updateSiteDeployment($siteId, $deploymentId); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals(true, $dateValidator->isValid($response['body']['$createdAt'])); + $this->assertEquals(true, $dateValidator->isValid($response['body']['$updatedAt'])); + $this->assertEquals($deploymentId, $response['body']['deploymentId']); + + $this->cleanupDeployment($siteId, $deploymentId); + $this->cleanupSite($siteId); + } + + public function testListDeployments(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'false' + ]); + + $deploymentIdActive = $deployment['body']['$id'] ?? ''; + $this->assertEquals(202, $deployment['headers']['status-code']); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'false' + ]); + + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + + $deploymentIdInactive = $deployment['body']['$id'] ?? ''; + + $deployments = $this->listDeployments($siteId); + + $this->assertEquals($deployments['headers']['status-code'], 200); + $this->assertEquals($deployments['body']['total'], 2); + $this->assertIsArray($deployments['body']['deployments']); + $this->assertCount(2, $deployments['body']['deployments']); + $this->assertArrayHasKey('sourceSize', $deployments['body']['deployments'][0]); + $this->assertArrayHasKey('buildSize', $deployments['body']['deployments'][0]); + + $deployments = $this->listDeployments($siteId, [ + 'queries' => [ + Query::limit(1)->toString(), + ], + ]); + + $this->assertEquals($deployments['headers']['status-code'], 200); + $this->assertCount(1, $deployments['body']['deployments']); + + $deployments = $this->listDeployments($siteId, [ + 'queries' => [ + Query::offset(1)->toString(), + ], + ]); + + $this->assertEquals($deployments['headers']['status-code'], 200); + $this->assertCount(1, $deployments['body']['deployments']); + + $deployments = $this->listDeployments( + $siteId, + [ + 'queries' => [ + Query::equal('type', ['manual'])->toString(), + ], + ] + ); + + $this->assertEquals($deployments['headers']['status-code'], 200); + $this->assertEquals(2, $deployments['body']['total']); + + $deployments = $this->listDeployments( + $siteId, + [ + 'queries' => [ + Query::equal('type', ['vcs'])->toString(), + ], + ] + ); + + $this->assertEquals($deployments['headers']['status-code'], 200); + $this->assertEquals(0, $deployments['body']['total']); + + $deployments = $this->listDeployments( + $siteId, + [ + 'queries' => [ + Query::equal('type', ['invalid-string'])->toString(), + ], + ] + ); + + $this->assertEquals($deployments['headers']['status-code'], 200); + $this->assertEquals(0, $deployments['body']['total']); + + $deployments = $this->listDeployments( + $siteId, + [ + 'queries' => [ + Query::greaterThan('sourceSize', 10000)->toString(), + ], + ] + ); + + $this->assertEquals($deployments['headers']['status-code'], 200); + $this->assertEquals(0, $deployments['body']['total']); + + $deployments = $this->listDeployments( + $siteId, + [ + 'queries' => [ + Query::greaterThan('sourceSize', 0)->toString(), + ], + ] + ); + + $this->assertEquals($deployments['headers']['status-code'], 200); + $this->assertEquals(2, $deployments['body']['total']); + + $deployments = $this->listDeployments( + $siteId, + [ + 'queries' => [ + Query::greaterThan('sourceSize', -100)->toString(), + ], + ] + ); + $this->assertEquals($deployments['headers']['status-code'], 200); + $this->assertEquals(2, $deployments['body']['total']); + + /** + * Ensure size output and size filters work exactly. + * Prevents buildSize being counted towards deployment size + */ + $deployments = $this->listDeployments( + $siteId, + [ + Query::limit(1)->toString(), + ] + ); + + $this->assertEquals(200, $deployments['headers']['status-code']); + $this->assertGreaterThanOrEqual(1, $deployments['body']['total']); + $this->assertNotEmpty($deployments['body']['deployments'][0]['$id']); + $this->assertNotEmpty($deployments['body']['deployments'][0]['sourceSize']); + + $deploymentId = $deployments['body']['deployments'][0]['$id']; + $deploymentSize = $deployments['body']['deployments'][0]['sourceSize']; + + $deployments = $this->listDeployments( + $siteId, + [ + 'queries' => [ + Query::equal('sourceSize', [$deploymentSize])->toString(), + ], + ] + ); + + $this->assertEquals(200, $deployments['headers']['status-code']); + $this->assertGreaterThan(0, $deployments['body']['total']); + + $matchingDeployment = array_filter( + $deployments['body']['deployments'], + fn ($deployment) => $deployment['$id'] === $deploymentId + ); + + $this->assertNotEmpty($matchingDeployment, "Deployment with ID {$deploymentId} not found"); + + if (!empty($matchingDeployment)) { + $deployment = reset($matchingDeployment); + $this->assertEquals($deploymentSize, $deployment['sourceSize']); + } + + $this->cleanupDeployment($siteId, $deploymentIdActive); + $this->cleanupDeployment($siteId, $deploymentIdInactive); + $this->cleanupSite($siteId); + } + + public function testGetDeployment(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'false' + ]); + + $deploymentId = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($siteId, $deploymentId) { + $deployment = $this->getDeployment($siteId, $deploymentId); + + $this->assertEquals('ready', $deployment['body']['status']); + }, 50000, 500); + + /** + * Test for SUCCESS + */ + $deployment = $this->getDeployment($siteId, $deploymentId); + + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertGreaterThan(0, $deployment['body']['buildDuration']); + $this->assertNotEmpty($deployment['body']['status']); + $this->assertNotEmpty($deployment['body']['buildLogs']); + $this->assertArrayHasKey('sourceSize', $deployment['body']); + $this->assertArrayHasKey('buildSize', $deployment['body']); + + /** + * Test for FAILURE + */ + $deployment = $this->getDeployment($siteId, 'x'); + + $this->assertEquals($deployment['headers']['status-code'], 404); + + $this->cleanupDeployment($siteId, $deploymentId); + $this->cleanupSite($siteId); + } + + public function testUpdateSpecs(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + /** + * Test for SUCCESS + */ + // Change the function specs + $site = $this->updateSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + '$id' => $siteId, + 'specification' => Specification::S_1VCPU_1GB, + ]); + + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertNotEmpty($site['body']['$id']); + $this->assertEquals(Specification::S_1VCPU_1GB, $site['body']['specification']); + + // Change the specs to 1vcpu 512mb + $site = $this->updateSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + '$id' => $siteId, + 'specification' => Specification::S_1VCPU_512MB, + ]); + + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertNotEmpty($site['body']['$id']); + $this->assertEquals(Specification::S_1VCPU_512MB, $site['body']['specification']); + + /** + * Test for FAILURE + */ + + $site = $this->updateSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + '$id' => $siteId, + 'specification' => 's-2vcpu-512mb', // Invalid specification + ]); + + $this->assertEquals(400, $site['headers']['status-code']); + $this->assertStringStartsWith('Invalid `specification` param: Specification must be one of:', $site['body']['message']); + + $this->cleanupSite($siteId); + } + + public function testDeleteDeployment(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'false' + ]); + + $deploymentId = $deployment['body']['$id'] ?? ''; + + $this->assertEventually(function () use ($siteId, $deploymentId) { + $deployment = $this->getDeployment($siteId, $deploymentId); + + $this->assertEquals('ready', $deployment['body']['status']); + }, 50000, 500); + + /** + * Test for SUCCESS + */ + $deployment = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(204, $deployment['headers']['status-code']); + $this->assertEmpty($deployment['body']); + + $deployment = $this->getDeployment($siteId, $deploymentId); + + $this->assertEquals(404, $deployment['headers']['status-code']); + } + + public function testDeleteSite(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $this->assertNotNull($siteId); + + $site = $this->deleteSite($siteId); + + $this->assertEquals(204, $site['headers']['status-code']); + $this->assertEmpty($site['body']); + + $function = $this->getSite($siteId); + + $this->assertEquals(404, $function['headers']['status-code']); + } + + public function testGetFrameworks(): void + { + $frameworks = $this->client->call(Client::METHOD_GET, '/sites/frameworks', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + + $this->assertEquals(200, $frameworks['headers']['status-code']); + $this->assertGreaterThan(0, $frameworks['body']['total']); + + $framework = $frameworks['body']['frameworks'][0]; + + $this->assertArrayHasKey('name', $framework); + $this->assertArrayHasKey('key', $framework); + $this->assertArrayHasKey('buildRuntime', $framework); + $this->assertArrayHasKey('runtimes', $framework); + $this->assertArrayHasKey('adapters', $framework); + $this->assertIsArray($framework['adapters']); + $this->assertArrayHasKey('key', $framework['adapters'][0]); + $this->assertArrayHasKey('installCommand', $framework['adapters'][0]); + $this->assertArrayHasKey('buildCommand', $framework['adapters'][0]); + $this->assertArrayHasKey('outputDirectory', $framework['adapters'][0]); + } + + public function testSiteStatic(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Non-SPA site', + 'framework' => 'other', + 'adapter' => 'static', + 'buildRuntime' => 'static-1', + 'outputDirectory' => './', + 'buildCommand' => '', + 'installCommand' => '', + 'fallbackFile' => '', + ]); + + $this->assertNotEmpty($siteId); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static-spa'), + 'activate' => 'true' + ]); + + $this->assertNotEmpty($deploymentId); + + $domain = $this->setupSiteDomain($siteId); + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Index page", $response['body']); + + $response = $proxyClient->call(Client::METHOD_GET, '/contact', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Contact page", $response['body']); + + $response = $proxyClient->call(Client::METHOD_GET, '/non-existing', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + + $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->cleanupSite($siteId); + } + + public function testSiteStaticSPA(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'SPA site', + 'framework' => 'other', + 'adapter' => 'static', + 'buildRuntime' => 'static-1', + 'outputDirectory' => './', + 'buildCommand' => '', + 'installCommand' => '', + 'fallbackFile' => '404.html', + ]); + + $this->assertNotEmpty($siteId); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static-spa'), + 'activate' => 'true' + ]); + + $this->assertNotEmpty($deploymentId); + + $domain = $this->setupSiteDomain($siteId); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Index page", $response['body']); + + $response = $proxyClient->call(Client::METHOD_GET, '/contact', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Contact page", $response['body']); + + $response = $proxyClient->call(Client::METHOD_GET, '/non-existing', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Customized 404 page", $response['body']); + $this->assertStringNotContainsString("Powered by", $response['body']); // Brand + + $this->cleanupSite($siteId); + } + + public function testSiteTemplate(): void + { + $template = $this->getTemplate('astro-starter'); + $this->assertEquals(200, $template['headers']['status-code']); + + $template = $template['body']; + + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Template site', + 'framework' => $template['frameworks'][0]['key'], + 'adapter' => $template['frameworks'][0]['adapter'], + 'buildRuntime' => $template['frameworks'][0]['buildRuntime'], + 'outputDirectory' => $template['frameworks'][0]['outputDirectory'], + 'buildCommand' => $template['frameworks'][0]['buildCommand'], + 'installCommand' => $template['frameworks'][0]['installCommand'], + 'fallbackFile' => $template['frameworks'][0]['fallbackFile'], + ]); + + $this->assertNotEmpty($siteId); + + $deployment = $this->createTemplateDeployment($siteId, [ + 'repository' => $template['providerRepositoryId'], + 'owner' => $template['providerOwner'], + 'rootDirectory' => $template['frameworks'][0]['providerRootDirectory'], + 'version' => $template['providerVersion'], + 'activate' => true + ]); + + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + + $deployment = $this->getDeployment($siteId, $deployment['body']['$id']); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertEquals(0, $deployment['body']['sourceSize']); + $this->assertEquals(0, $deployment['body']['buildSize']); + $this->assertEquals(0, $deployment['body']['totalSize']); + + $this->assertEventually(function () use ($siteId) { + $site = $this->getSite($siteId); + $this->assertNotEmpty($site['body']['deploymentId']); + }, 50000, 500); + + $domain = $this->setupSiteDomain($siteId); + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Astro Blog", $response['body']); + $this->assertStringContainsString("Hello, Astronaut!", $response['body']); + + $response = $proxyClient->call(Client::METHOD_GET, '/about'); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Astro Blog", $response['body']); + $this->assertStringContainsString("About Me", $response['body']); + + $deployment = $this->getDeployment($siteId, $deployment['body']['$id']); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertGreaterThan(0, $deployment['body']['sourceSize']); + $this->assertGreaterThan(0, $deployment['body']['buildSize']); + $totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize']; + $this->assertEquals($totalSize, $deployment['body']['totalSize']); + + $this->cleanupSite($siteId); + } + + public function testSiteDomainReclaiming(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Startup site', + 'framework' => 'other', + 'adapter' => 'static', + 'buildRuntime' => 'static-1', + 'outputDirectory' => './', + 'buildCommand' => '', + 'installCommand' => '', + 'fallbackFile' => '', + ]); + + $this->assertNotEmpty($siteId); + + $subdomain = 'startup' . \uniqid(); + $domain = $this->setupSiteDomain($siteId, $subdomain); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'true' + ]); + + $this->assertNotEmpty($deploymentId); + + $domain = $this->getSiteDomain($siteId); + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringNotContainsString("This domain is not connected to any Appwrite resource yet", $response['body']); + + $site2 = $this->createSite([ + 'siteId' => ID::unique(), + 'name' => 'Startup 2 site', + 'framework' => 'other', + 'adapter' => 'static', + 'buildRuntime' => 'static-1', + 'outputDirectory' => './', + 'buildCommand' => '', + 'installCommand' => '', + 'fallbackFile' => '', + ]); + + $siteId2 = $site2['body']['$id']; + + $rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/site', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'domain' => $subdomain . '.' . System::getEnv('_APP_DOMAIN_SITES', ''), + 'siteId' => $siteId2, + ]); + + $this->assertEquals(409, $rule['headers']['status-code']); + + $this->cleanupSite($siteId); + + $this->assertEventually(function () use ($domain) { + $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('domain', [$domain])->toString(), + ], + ]); + + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(0, $rules['body']['total']); + }, 50000, 500); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + + $this->assertEquals(404, $response['headers']['status-code']); + $this->assertStringContainsString("This page is empty, but you can make it yours.", $response['body']); + + $site = $this->createSite([ + 'siteId' => ID::unique(), + 'name' => 'Startup 2 site', + 'framework' => 'other', + 'adapter' => 'static', + 'buildRuntime' => 'static-1', + 'outputDirectory' => './', + 'buildCommand' => '', + 'installCommand' => '', + 'fallbackFile' => '', + ]); + + $this->assertEquals(201, $site['headers']['status-code']); + $this->assertNotEmpty($site['body']['$id']); + + $siteId = $site['body']['$id']; + + $domain = $this->setupSiteDomain($siteId, $subdomain); + + $this->assertNotEmpty($domain); + + $this->cleanupSite($site['body']['$id']); + } + + public function testSitePreviewBranding(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'A site', + 'framework' => 'other', + 'adapter' => 'static', + 'buildRuntime' => 'static-1', + 'outputDirectory' => './', + 'buildCommand' => '', + 'installCommand' => '', + 'fallbackFile' => '', + ]); + + $this->assertNotEmpty($siteId); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId); + + $siteDomain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($siteDomain); + + $deploymentDomain = $this->getDeploymentDomain($deploymentId); + $this->assertNotEmpty($deploymentDomain); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $siteDomain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Hello Appwrite", $response['body']); + $this->assertStringNotContainsString("Preview by", $response['body']); + $contentLength = $response['headers']['content-length']; + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $deploymentDomain); + $response = $proxyClient->call(Client::METHOD_GET, '/', followRedirects: false); + $this->assertEquals(301, $response['headers']['status-code']); + $this->assertStringContainsString('/console/auth/preview', $response['headers']['location']); + + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 0); + $apiKey = $jwtObj->encode([ + 'projectCheckDisabled' => true, + 'previewAuthDisabled' => true, + ]); + $response = $proxyClient->call(Client::METHOD_GET, '/', followRedirects: false, headers: [ + 'x-appwrite-key' => API_KEY_DYNAMIC . '_' . $apiKey, + ]); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Hello Appwrite", $response['body']); + $this->assertStringContainsString("Preview by", $response['body']); + $this->assertGreaterThan($contentLength, $response['headers']['content-length']); + + $response = $proxyClient->call(Client::METHOD_GET, '/non-existing-path', followRedirects: false, headers: [ + 'x-appwrite-key' => API_KEY_DYNAMIC . '_' . $apiKey, + ]); + $this->assertEquals(404, $response['headers']['status-code']); + $this->assertStringContainsString("Page not found", $response['body']); + $this->assertStringNotContainsString("Preview by", $response['body']); + $this->assertGreaterThan($contentLength, $response['headers']['content-length']); + + $this->cleanupSite($siteId); + } + + public function testSiteCors(): void + { + // Create rule together with site + $subdomain = 'startup' . \uniqid(); + + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Startup site', + 'framework' => 'other', + 'adapter' => 'static', + 'buildRuntime' => 'static-1', + 'outputDirectory' => './', + 'buildCommand' => '', + 'installCommand' => '', + 'fallbackFile' => '', + 'subdomain' => $subdomain + ]); + + $this->assertNotEmpty($siteId); + + $this->setupSiteDomain($siteId, $subdomain); + $domain = $this->getSiteDomain($siteId); + + $this->assertNotEmpty($domain); + + $url = 'http://' . $domain; + + $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'referer' => $url, + 'origin' => $url + ])); + + $this->assertEquals($url, $response['headers']['access-control-allow-origin']); + + $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => 'unknown', + 'referer' => $url, + 'origin' => $url + ])); + + $this->assertNotEquals($url, $response['headers']['access-control-allow-origin']); + $this->assertEquals('http://localhost', $response['headers']['access-control-allow-origin']); + + $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'referer' => 'http://unknown.com', + 'origin' => 'http://unknown.com' + ])); + + $this->assertNotEquals($url, $response['headers']['access-control-allow-origin']); + $this->assertEquals('http://localhost', $response['headers']['access-control-allow-origin']); + } + + public function testSiteScreenshot(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Themed site', + 'framework' => 'other', + 'adapter' => 'static', + 'buildRuntime' => 'static-1', + 'outputDirectory' => './', + 'buildCommand' => '', + 'installCommand' => '', + 'fallbackFile' => '', + ]); + + $this->assertNotEmpty($siteId); + + $domain = $this->setupSiteDomain($siteId); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static-themed'), + 'activate' => 'true' + ]); + + $this->assertNotEmpty($deploymentId); + + $domain = $this->getSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Themed website", $response['body']); + $this->assertStringContainsString("@media (prefers-color-scheme: dark)", $response['body']); + + $deployment = $this->getDeployment($siteId, $deploymentId); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['screenshotLight']); + $this->assertNotEmpty($deployment['body']['screenshotDark']); + + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deployment['body']['screenshotLight'], $site['body']['deploymentScreenshotLight']); + $this->assertEquals($deployment['body']['screenshotDark'], $site['body']['deploymentScreenshotDark']); + + $screenshotId = $deployment['body']['screenshotLight']; + $file = $this->client->call(Client::METHOD_GET, "/storage/buckets/screenshots/files/$screenshotId/view?project=console", array_merge([ + ], $this->getHeaders())); + + $this->assertEquals(200, $file['headers']['status-code']); + $this->assertNotEmpty(200, $file['body']); + $this->assertGreaterThan(1, $file['headers']['content-length']); + $this->assertEquals('image/png', $file['headers']['content-type']); + + $screenshotHash = \md5($file['body']); + $this->assertNotEmpty($screenshotHash); + + $screenshotId = $deployment['body']['screenshotDark']; + $file = $this->client->call(Client::METHOD_GET, "/storage/buckets/screenshots/files/$screenshotId/view?project=console", array_merge([ + ], $this->getHeaders())); + + $this->assertEquals(200, $file['headers']['status-code']); + $this->assertNotEmpty(200, $file['body']); + $this->assertGreaterThan(1, $file['headers']['content-length']); + $this->assertEquals('image/png', $file['headers']['content-type']); + + $screenshotDarkHash = \md5($file['body']); + $this->assertNotEmpty($screenshotDarkHash); + + $this->assertNotEquals($screenshotDarkHash, $screenshotHash); + + $file = $this->client->call(Client::METHOD_GET, "/storage/buckets/screenshots/files/$screenshotId/view?project=console"); + $this->assertEquals(404, $file['headers']['status-code']); + + $file = $this->client->call(Client::METHOD_GET, "/storage/buckets/screenshots/files/$screenshotId/view?project=console"); + $this->assertEquals(404, $file['headers']['status-code']); + + $this->cleanupSite($siteId); + } + + public function testSiteDownload(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'fallbackFile' => '', + 'framework' => 'other', + 'name' => 'Test Site', + 'adapter' => 'static', + 'outputDirectory' => './', + 'providerBranch' => 'main', + 'providerRootDirectory' => './', + 'siteId' => ID::unique() + ]); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => true + ]); + + $this->assertNotEmpty($deploymentId); + + $response = $this->getDeploymentDownload($siteId, $deploymentId, 'source'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('application/gzip', $response['headers']['content-type']); + $this->assertGreaterThan(0, $response['headers']['content-length']); + $this->assertGreaterThan(0, \strlen($response['body'])); + + $deploymentMd5 = \md5($response['body']); + + $response = $this->getDeploymentDownload($siteId, $deploymentId, 'output'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals('application/gzip', $response['headers']['content-type']); + $this->assertGreaterThan(0, $response['headers']['content-length']); + $this->assertGreaterThan(0, \strlen($response['body'])); + + $buildMd5 = \md5($response['body']); + + $this->assertNotEquals($deploymentMd5, $buildMd5); + + $this->cleanupSite($siteId); + } + + public function testSSRLogs(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'SSR site', + 'framework' => 'astro', + 'adapter' => 'ssr', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './dist', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'fallbackFile' => '', + ]); + + $this->assertNotEmpty($siteId); + + $domain = $this->setupSiteDomain($siteId); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('astro'), + 'activate' => 'true' + ]); + + $this->assertNotEmpty($deploymentId); + + $domain = $this->getSiteDomain($siteId); + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/logs-inline'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Inline logs printed.", $response['body']); + + $logs = $this->listLogs($siteId, [ + Query::orderDesc('$createdAt')->toString(), + Query::limit(1)->toString(), + ]); + $this->assertEquals(200, $logs['headers']['status-code']); + $this->assertStringContainsString("GET", $logs['body']['executions'][0]['requestMethod']); + $this->assertStringContainsString("/logs-inline", $logs['body']['executions'][0]['requestPath']); + $this->assertStringContainsString("Log1", $logs['body']['executions'][0]['logs']); + $this->assertStringContainsString("Log2", $logs['body']['executions'][0]['logs']); + $this->assertStringContainsString("Error1", $logs['body']['executions'][0]['errors']); + $this->assertStringContainsString("Error2", $logs['body']['executions'][0]['errors']); + $log1Id = $logs['body']['executions'][0]['$id']; + $this->assertNotEmpty($log1Id); + + $response = $proxyClient->call(Client::METHOD_GET, '/logs-action'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Action logs printed.", $response['body']); + + $logs = $this->listLogs($siteId, [ + Query::orderDesc('$createdAt')->toString(), + Query::limit(1)->toString(), + ]); + $this->assertEquals(200, $logs['headers']['status-code']); + $this->assertStringContainsString("GET", $logs['body']['executions'][0]['requestMethod']); + $this->assertStringContainsString("/logs-action", $logs['body']['executions'][0]['requestPath']); + $this->assertStringContainsString("Log1", $logs['body']['executions'][0]['logs']); + $this->assertStringContainsString("Log2", $logs['body']['executions'][0]['logs']); + $this->assertStringContainsString("Error1", $logs['body']['executions'][0]['errors']); + $this->assertStringContainsString("Error2", $logs['body']['executions'][0]['errors']); + $log2Id = $logs['body']['executions'][0]['$id']; + $this->assertNotEmpty($log2Id); + + $this->assertNotEquals($log1Id, $log2Id); + + $site = $this->updateSite( + [ + '$id' => $siteId, + 'name' => 'SSR site', + 'framework' => 'astro', + 'adapter' => 'ssr', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './dist', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + 'fallbackFile' => '', + 'logging' => false // set logging to false + ] + ); + $this->assertEquals(200, $site['headers']['status-code']); + $response = $proxyClient->call(Client::METHOD_GET, '/logs-inline'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Inline logs printed.", $response['body']); + + $logs = $this->listLogs($siteId, [ + Query::orderDesc('$createdAt')->toString(), + Query::limit(1)->toString(), + ]); + $this->assertEquals(200, $logs['headers']['status-code']); + $this->assertEquals("GET", $logs['body']['executions'][0]['requestMethod']); + $this->assertEquals("/logs-inline", $logs['body']['executions'][0]['requestPath']); + $this->assertEmpty($logs['body']['executions'][0]['logs']); + $this->assertEmpty($logs['body']['executions'][0]['logs']); + $this->assertEmpty($logs['body']['executions'][0]['errors']); + $this->assertEmpty($logs['body']['executions'][0]['errors']); + $log1Id = $logs['body']['executions'][0]['$id']; + $this->assertNotEmpty($log1Id); + + $response = $proxyClient->call(Client::METHOD_GET, '/logs-action'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Action logs printed.", $response['body']); + + $logs = $this->listLogs($siteId, [ + Query::orderDesc('$createdAt')->toString(), + Query::limit(1)->toString(), + ]); + $this->assertEquals(200, $logs['headers']['status-code']); + $this->assertEquals("GET", $logs['body']['executions'][0]['requestMethod']); + $this->assertEquals("/logs-action", $logs['body']['executions'][0]['requestPath']); + $this->assertEmpty($logs['body']['executions'][0]['logs']); + $this->assertEmpty($logs['body']['executions'][0]['logs']); + $this->assertEmpty($logs['body']['executions'][0]['errors']); + $this->assertEmpty($logs['body']['executions'][0]['errors']); + $log2Id = $logs['body']['executions'][0]['$id']; + $this->assertNotEmpty($log2Id); + + $this->cleanupSite($siteId); + } + + public function testDuplicateDeployment(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'framework' => 'other', + 'name' => 'Duplicate deployment Site', + 'adapter' => 'static', + 'fallbackFile' => '404.html', + 'siteId' => ID::unique() + ]); + $this->assertNotEmpty($siteId); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $deploymentId1 = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static-spa'), + 'activate' => true + ]); + $this->assertNotEmpty($deploymentId1); + + $response = $proxyClient->call(Client::METHOD_GET, '/not-found'); + $this->assertStringContainsString("Customized 404 page", $response['body']); + + $site = $this->updateSite([ + '$id' => $siteId, + 'buildRuntime' => 'node-22', + 'framework' => 'other', + 'name' => 'Duplicate deployment Site', + 'adapter' => 'static', + 'fallbackFile' => 'index.html', + ]); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals('index.html', $site['body']['fallbackFile']); + + $deployment = $this->createDuplicateDeployment($siteId, $deploymentId1); + $this->assertEquals(202, $deployment['headers']['status-code']); + + $deploymentId2 = $deployment['body']['$id']; + $this->assertNotEmpty($deploymentId2); + + $deployment = $this->getDeployment($siteId, $deploymentId2); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertGreaterThan(0, $deployment['body']['sourceSize']); + $this->assertEquals(0, $deployment['body']['buildSize']); + $this->assertEquals($deployment['body']['sourceSize'], $deployment['body']['totalSize']); + + $this->assertEventually(function () use ($siteId, $deploymentId2) { + $site = $this->getSite($siteId); + $this->assertEquals($deploymentId2, $site['body']['deploymentId']); + }, 50000, 500); + + $response = $proxyClient->call(Client::METHOD_GET, '/not-found'); + $this->assertStringContainsString("Index page", $response['body']); + + $deployment = $this->getDeployment($siteId, $deploymentId2); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertGreaterThan(0, $deployment['body']['sourceSize']); + $this->assertGreaterThan(0, $deployment['body']['buildSize']); + $totalSize = $deployment['body']['sourceSize'] + $deployment['body']['buildSize']; + $this->assertEquals($totalSize, $deployment['body']['totalSize']); + + $this->cleanupSite($siteId); + } + + public function testUpdateDeploymentStatus(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'framework' => 'other', + 'name' => 'Activate test Site', + 'siteId' => ID::unique(), + 'adapter' => 'static', + ]); + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertArrayHasKey('latestDeploymentId', $site['body']); + $this->assertArrayHasKey('latestDeploymentCreatedAt', $site['body']); + $this->assertArrayHasKey('latestDeploymentStatus', $site['body']); + $this->assertEmpty($site['body']['latestDeploymentId']); + $this->assertEmpty($site['body']['latestDeploymentCreatedAt']); + $this->assertEmpty($site['body']['latestDeploymentStatus']); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $deploymentId1 = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => true + ]); + $this->assertNotEmpty($deploymentId1); + + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId1, $site['body']['latestDeploymentId']); + $this->assertEquals('ready', $site['body']['latestDeploymentStatus']); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString('Hello Appwrite', $response['body']); + + $deploymentId2 = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static-spa'), + 'activate' => true + ]); + $this->assertNotEmpty($deploymentId2); + + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId2, $site['body']['latestDeploymentId']); + $this->assertEquals('ready', $site['body']['latestDeploymentStatus']); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString('Index page', $response['body']); + + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId2, $site['body']['deploymentId']); + $this->assertEquals($deploymentId2, $site['body']['latestDeploymentId']); + $this->assertEquals('ready', $site['body']['latestDeploymentStatus']); + + $site = $this->updateSiteDeployment($siteId, $deploymentId1); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId1, $site['body']['deploymentId']); + + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId1, $site['body']['deploymentId']); + $this->assertEquals($deploymentId2, $site['body']['latestDeploymentId']); + $this->assertEquals('ready', $site['body']['latestDeploymentStatus']); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString('Hello Appwrite', $response['body']); + + $deployment = $this->deleteDeployment($siteId, $deploymentId2); + $this->assertEquals(204, $deployment['headers']['status-code']); + + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertEquals($deploymentId1, $site['body']['latestDeploymentId']); + $this->assertEquals('ready', $site['body']['latestDeploymentStatus']); + + $this->cleanupSite($siteId); + } + + public function testPreviewDomain(): void + { + $siteId = $this->setupSite([ + 'buildRuntime' => 'node-22', + 'framework' => 'other', + 'name' => 'Authorized preview site', + 'siteId' => ID::unique(), + 'adapter' => 'static', + ]); + $this->assertNotEmpty($siteId); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => true + ]); + $this->assertNotEmpty($deploymentId); + + $domain = $this->getDeploymentDomain($deploymentId); + $this->assertNotEmpty($domain); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/contact', followRedirects: false); + $this->assertEquals(301, $response['headers']['status-code']); + $this->assertStringContainsString('/console/auth/preview', $response['headers']['location']); + $this->assertStringContainsString('projectId=' . $this->getProject()['$id'], $response['headers']['location']); + $this->assertStringContainsString('origin=', $response['headers']['location']); + $this->assertStringContainsString('path=%2Fcontact', $response['headers']['location']); + + $session = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + ]), [ + 'email' => $this->getRoot()['email'], + 'password' => 'password' + ]); + $this->assertEquals(201, $session['headers']['status-code']); + $this->assertNotEmpty($session['cookies']['a_session_console']); + $this->assertNotEmpty($session['body']['$id']); + $cookie = 'a_session_console=' . $session['cookies']['a_session_console']; + + $jwt = $this->client->call(Client::METHOD_POST, '/account/jwts', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => $cookie, + 'x-appwrite-project' => 'console', + ]), []); + $this->assertEquals(201, $jwt['headers']['status-code']); + $this->assertNotEmpty($jwt['body']['jwt']); + + $response = $proxyClient->call(Client::METHOD_GET, '/_appwrite/authorize', params: [ + 'jwt' => $jwt['body']['jwt'], + 'path' => '/contact' + ], followRedirects: false); + $this->assertEquals(301, $response['headers']['status-code']); + $this->assertArrayHasKey('set-cookie', $response['headers']); + $this->assertStringContainsString('a_jwt_console=', $response['headers']['set-cookie']); + $this->assertStringContainsString('httponly', $response['headers']['set-cookie']); + $this->assertStringContainsString('domain=' . $domain, $response['headers']['set-cookie']); + $this->assertStringContainsString('path=/', $response['headers']['set-cookie']); + $this->assertNotEmpty($response['cookies']['a_jwt_console']); + $this->assertEquals($jwt['body']['jwt'], $response['cookies']['a_jwt_console']); + + $response = $proxyClient->call(Client::METHOD_GET, '/contact', headers: [ + 'cookie' => 'a_jwt_console=' . $jwt['body']['jwt'] + ], followRedirects: false); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Contact page", $response['body']); + $this->assertStringContainsString("Preview by", $response['body']); + + // Failure: Session missing (old bad, new ok) + $session = $this->client->call(Client::METHOD_DELETE, '/account/sessions/current', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => $cookie, + 'x-appwrite-project' => 'console', + ]), []); + $this->assertEquals(204, $session['headers']['status-code']); + + $response = $proxyClient->call(Client::METHOD_GET, '/contact', headers: [ + 'cookie' => 'a_jwt_console=' . $jwt['body']['jwt'] + ], followRedirects: false); + $this->assertEquals(301, $response['headers']['status-code']); + $this->assertStringContainsString('/console/auth/preview', $response['headers']['location']); + + // Failure: User missing + $cookie = 'a_session_console=' .$this->getRoot()['session']; + $jwt = $this->client->call(Client::METHOD_POST, '/account/jwts', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => $cookie, + 'x-appwrite-project' => 'console', + ]), []); + $this->assertEquals(201, $jwt['headers']['status-code']); + $this->assertNotEmpty($jwt['body']['jwt']); + + $response = $proxyClient->call(Client::METHOD_GET, '/contact', headers: [ + 'cookie' => 'a_jwt_console=' . $jwt['body']['jwt'] + ], followRedirects: false); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString("Contact page", $response['body']); + $this->assertStringContainsString("Preview by", $response['body']); + + $user = $this->client->call(Client::METHOD_PATCH, '/account/status', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => $cookie, + 'x-appwrite-project' => 'console', + ]), []); + $this->assertEquals(200, $user['headers']['status-code']); + $this->assertFalse($user['body']['status']); + + $response = $proxyClient->call(Client::METHOD_GET, '/contact', headers: [ + 'cookie' => 'a_jwt_console=' . $jwt['body']['jwt'] + ], followRedirects: false); + $this->assertEquals(301, $response['headers']['status-code']); + $this->assertStringContainsString('/console/auth/preview', $response['headers']['location']); + + // Failure: Membership missing + $email = \uniqid() . 'newuser@appwrite.io'; + $user = $this->client->call(Client::METHOD_POST, '/account', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + ], [ + 'userId' => ID::unique(), + 'email' => $email, + 'password' => 'password' + ]); + $this->assertEquals(201, $user['headers']['status-code']); + + $session = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + ], [ + 'email' => $email, + 'password' => 'password', + ]); + $this->assertEquals(201, $session['headers']['status-code']); + $this->assertNotEmpty($session['cookies']['a_session_console']); + $cookie = 'a_session_console=' . $session['cookies']['a_session_console']; + + $jwt = $this->client->call(Client::METHOD_POST, '/account/jwts', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'cookie' => $cookie, + 'x-appwrite-project' => 'console', + ]), []); + $this->assertEquals(201, $jwt['headers']['status-code']); + $this->assertNotEmpty($jwt['body']['jwt']); + + $response = $proxyClient->call(Client::METHOD_GET, '/contact', headers: [ + 'cookie' => 'a_jwt_console=' . $jwt['body']['jwt'] + ], followRedirects: false); + $this->assertEquals(301, $response['headers']['status-code']); + $this->assertStringContainsString('/console/auth/preview', $response['headers']['location']); + + $this->cleanupSite($siteId); + } + + public function testInvalidSSRSource(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Astro SSR Site', + 'framework' => 'astro', + 'adapter' => 'ssr', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './dist', + 'buildCommand' => 'npm run build', + 'installCommand' => 'npm install', + ]); + + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals(200, $site['headers']['status-code']); + $this->assertArrayHasKey('adapter', $site['body']); + $this->assertEquals('ssr', $site['body']['adapter']); + + $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); + + $this->cleanupSite($siteId); + } + + public function testDomainForFailedDeloyment(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Test Site', + 'framework' => 'astro', + 'buildRuntime' => 'node-22', + 'buildCommand' => 'cd random' + ]); + + $this->assertNotEmpty($siteId); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('astro'), + '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'], json_encode($deployment['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertStringContainsString('This page is empty, activate a deployment to make it live.', $response['body']); + + $this->cleanupSite($siteId); + } + + public function testPermanentRedirect(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Sub project site', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './' + ]); + $this->assertNotEmpty($siteId); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('sub-directories'), + 'activate' => 'true' + ]); + $this->assertNotEmpty($deploymentId); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertStringContainsString('Sub-directory index', $response['body']); + $response1 = $proxyClient->call(Client::METHOD_GET, '/project1'); + $this->assertEquals(200, $response1['headers']['status-code']); + $this->assertStringContainsString('Sub-directory project1', $response1['body']); + $response2 = $proxyClient->call(Client::METHOD_GET, '/project1/'); + $this->assertEquals(200, $response2['headers']['status-code']); + $this->assertStringContainsString('Sub-directory project1', $response2['body']); + $this->cleanupSite($siteId); + } + + public function testDeploymentCommandEscaping(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'A site', + 'framework' => 'other', + 'adapter' => 'static', + 'buildRuntime' => 'static-1', + 'outputDirectory' => './', + 'buildCommand' => "echo 'Hello two'", + 'installCommand' => 'echo "Hello one"', + 'fallbackFile' => '', + ]); + + $this->assertNotEmpty($siteId); + + $deploymentId = $this->setupDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'true' + ]); + + $this->assertNotEmpty($deploymentId); + + $deployment = $this->getDeployment($siteId, $deploymentId); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertStringContainsString('Hello one', $deployment['body']['buildLogs']); + $this->assertStringContainsString('Hello two', $deployment['body']['buildLogs']); + + $this->cleanupSite($siteId); + } + + #[Retry(count: 3)] + public function testErrorPages(): void + { + // non-existent domain page + $domain = 'non-existent-page.sites.localhost'; + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/'); + + $this->assertEquals(404, $response['headers']['status-code']); + $this->assertStringContainsString('Nothing is here yet', $response['body']); + $this->assertStringContainsString('Start with this domain', $response['body']); + + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Static site', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './', + 'buildCommand' => 'sleep 5 && cd non-existing-directory', + ]); + $this->assertNotEmpty($siteId); + + $domain = $this->setupSiteDomain($siteId); + + // test canceled deployment error page + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('static'), + 'activate' => 'true' + ]); + $deploymentId = $deployment['body']['$id'] ?? ''; + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + + $deployment = $this->cancelDeployment($siteId, $deploymentId); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertEquals('canceled', $deployment['body']['status']); + + $deploymentDomain = $this->getDeploymentDomain($deploymentId); + $this->assertNotEmpty($deploymentDomain); + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $deploymentDomain); + $response = $proxyClient->call(Client::METHOD_GET, '/', followRedirects: false); + $this->assertEquals(301, $response['headers']['status-code']); + + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 0); + $apiKey = $jwtObj->encode([ + 'projectCheckDisabled' => true, + 'previewAuthDisabled' => true, + ]); + + $response = $proxyClient->call(Client::METHOD_GET, '/', followRedirects: false, headers: [ + 'x-appwrite-key' => API_KEY_DYNAMIC . '_' . $apiKey, + ]); + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertStringContainsString("Deployment build canceled", $response['body']); + $this->assertStringContainsString("View deployments", $response['body']); + + // check site domain for no active deployments + $proxyClient->setEndpoint('http://' . $domain); + $response = $proxyClient->call(Client::METHOD_GET, '/'); + $this->assertEquals(404, $response['headers']['status-code']); + $this->assertStringContainsString('No active deployments', $response['body']); + $this->assertStringContainsString('View deployments', $response['body']); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('astro'), + 'activate' => 'true' + ]); + + $deploymentId = $deployment['body']['$id'] ?? ''; + $this->assertNotEmpty($deploymentId); + + $deploymentDomain = $this->getDeploymentDomain($deploymentId); + $this->assertNotEmpty($deploymentDomain); + + $proxyClient->setEndpoint('http://' . $deploymentDomain); + $response = $proxyClient->call(Client::METHOD_GET, '/', followRedirects: false); + $this->assertEquals(301, $response['headers']['status-code']); + + // deployment is still building error page + $response = $proxyClient->call(Client::METHOD_GET, '/', followRedirects: false, headers: [ + 'x-appwrite-key' => API_KEY_DYNAMIC . '_' . $apiKey, + ]); + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertStringContainsString("Deployment is still building", $response['body']); + $this->assertStringContainsString("View logs", $response['body']); + $this->assertStringContainsString("Reload", $response['body']); + + $this->assertEventually(function () use ($siteId, $deploymentId) { + $deployment = $this->getDeployment($siteId, $deploymentId); + + $this->assertEquals('failed', $deployment['body']['status']); + }, 50000, 500); + + // deployment failed error page + $response = $proxyClient->call(Client::METHOD_GET, '/', followRedirects: false, headers: [ + 'x-appwrite-key' => API_KEY_DYNAMIC . '_' . $apiKey, + ]); + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertStringContainsString("Deployment build failed", $response['body']); + $this->assertStringContainsString("View logs", $response['body']); + + $this->cleanupSite($siteId); + } + + public function testEmptySiteSource(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Empty source site', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './', + ]); + $this->assertNotEmpty($siteId); + + // Prepare empty site folder + // We cant use .gitkeep, because that would make deployment non-empty + $stdout = ''; + $stderr = ''; + $folderPath = realpath(__DIR__ . '/../../../resources/sites') . '/empty'; + Console::execute("mkdir -p $folderPath", '', $stdout, $stderr); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('empty'), + '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 does not match: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + $this->assertStringContainsString('Error:', $deployment['body']['buildLogs'], 'Deployment logs do not match: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + $this->cleanupSite($siteId); + } + + public function testOutputDirectoryEmpty(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Empty output directory', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './empty-directory', + 'buildCommand' => 'mkdir -p ./empty-directory' + ]); + $this->assertNotEmpty($siteId); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('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 does not match: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + $this->assertStringContainsString('Error:', $deployment['body']['buildLogs'], 'Deployment logs do not match: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + $this->cleanupSite($siteId); + } + + public function testOutputDirectoryMissing(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Missing output directory', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './non-existing-directory', + ]); + $this->assertNotEmpty($siteId); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('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 does not match: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + $this->assertStringContainsString('Error:', $deployment['body']['buildLogs'], 'Deployment logs do not match: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + $this->cleanupSite($siteId); + } +} diff --git a/tests/e2e/Services/Storage/StorageConsoleClientTest.php b/tests/e2e/Services/Storage/StorageConsoleClientTest.php index 5b6731b35e..bbb14fb136 100644 --- a/tests/e2e/Services/Storage/StorageConsoleClientTest.php +++ b/tests/e2e/Services/Storage/StorageConsoleClientTest.php @@ -98,11 +98,13 @@ class StorageConsoleClientTest extends Scope ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(5, count($response['body'])); + $this->assertEquals(7, count($response['body'])); $this->assertEquals('24h', $response['body']['range']); $this->assertIsNumeric($response['body']['filesTotal']); $this->assertIsNumeric($response['body']['filesStorageTotal']); $this->assertIsArray($response['body']['files']); $this->assertIsArray($response['body']['storage']); + $this->assertIsArray($response['body']['imageTransformations']); + $this->assertIsNumeric($response['body']['imageTransformationsTotal']); } } diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 2328e4cdbf..80ac1621ee 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -37,6 +37,37 @@ trait TeamsBase $teamUid = $response1['body']['$id']; $teamName = $response1['body']['name']; + /** + * Test: Attempt to downgrade the only OWNER in an organization (should fail) + */ + if ($this->getProject()['$id'] === 'console') { + // Step 1: Fetch all team memberships — only one exists at this point + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::limit(1)->toString(), + ], + ]); + + // Step 2: Extract the membership ID of the only member (also the only OWNER) + $membershipID = $response['body']['memberships'][0]['$id']; + + // Step 3: Attempt to downgrade the member's role to 'developer' + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipID, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'roles' => ['developer'] + ]); + + // 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('There must be at least one owner in the organization.', $response['body']['message']); + } + $teamId = ID::unique(); $response2 = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 9188575932..3fcd9c043d 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -223,10 +223,8 @@ trait TeamsBaseClient $this->assertEquals($email, $lastEmail['to'][0]['address']); $this->assertEquals($name, $lastEmail['to'][0]['name']); $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); - - $secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); - $membershipUid = substr($lastEmail['text'], strpos($lastEmail['text'], '?membershipId=', 0) + 14, 20); - $userUid = substr($lastEmail['text'], strpos($lastEmail['text'], '&userId=', 0) + 8, 20); + $this->assertEquals($response['body']['teamId'], substr($lastEmail['text'], strpos($lastEmail['text'], '&teamId=', 0) + 8, 20)); + $this->assertEquals($teamName, substr($lastEmail['text'], strpos($lastEmail['text'], '&teamName=', 0) + 10, 7)); /** * Test with UserId @@ -290,11 +288,10 @@ trait TeamsBaseClient $this->assertEquals($secondEmail, $lastEmail['to'][0]['address']); $this->assertEquals($secondName, $lastEmail['to'][0]['name']); $this->assertEquals('Invitation to ' . $teamName . ' Team at ' . $this->getProject()['name'], $lastEmail['subject']); + $this->assertEquals($response['body']['teamId'], substr($lastEmail['text'], strpos($lastEmail['text'], '&teamId=', 0) + 8, 20)); + $this->assertEquals($teamName, substr($lastEmail['text'], strpos($lastEmail['text'], '&teamName=', 0) + 10, 7)); - /** - * Test for FAILURE - */ - + // test for resending invitation $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -305,7 +302,16 @@ trait TeamsBaseClient 'url' => 'http://localhost:5000/join-us#title' ]); - $this->assertEquals(409, $response['headers']['status-code']); + $this->assertEquals(201, $response['headers']['status-code']); + + $lastEmail = $this->getLastEmail(); + $membershipUid = substr($lastEmail['text'], strpos($lastEmail['text'], '?membershipId=', 0) + 14, 20); + $userUid = substr($lastEmail['text'], strpos($lastEmail['text'], '&userId=', 0) + 8, 20); + $secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); + + /** + * Test for FAILURE + */ $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', @@ -559,6 +565,76 @@ trait TeamsBaseClient return $data; } + + /** + * @depends testCreateTeam + */ + public function testUpdateMembershipWithSession(array $data): void + { + $teamUid = $data['teamUid'] ?? ''; + + // create user + $response = $this->client->call(Client::METHOD_POST, '/account', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'userId' => 'unique()', + 'email' => uniqid() . 'foe@localhost.test', + 'password' => 'password', + 'name' => 'test' + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $user = $response['body']; + + // create session + $response = $this->client->call(Client::METHOD_POST, '/account/sessions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], [ + 'email' => $user['email'], + 'password' => 'password' + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $session = $response['cookies']['a_session_' . $this->getProject()['$id']]; + + $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'email' => $user['email'], + 'roles' => ['developer'], + 'url' => 'http://localhost:5000/join-us#title' + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + + $lastEmail = $this->getLastEmail(); + + $secret = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); + $membershipUid = substr($lastEmail['text'], strpos($lastEmail['text'], '?membershipId=', 0) + 14, 20); + $userUid = substr($lastEmail['text'], strpos($lastEmail['text'], '&userId=', 0) + 8, 20); + + $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid . '/status', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ], [ + 'secret' => $secret, + 'userId' => $userUid, + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertNotEmpty($response['body']['userId']); + $this->assertNotEmpty($response['body']['teamId']); + $this->assertCount(1, $response['body']['roles']); + $this->assertEmpty($response['cookies']); + } + /** * @depends testUpdateTeamMembership */ @@ -648,7 +724,7 @@ trait TeamsBaseClient ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(3, $response['body']['total']); + $this->assertEquals(4, $response['body']['total']); $ownerMembershipUid = $response['body']['memberships'][0]['$id']; @@ -703,7 +779,7 @@ trait TeamsBaseClient ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(2, $response['body']['total']); + $this->assertEquals(3, $response['body']['total']); /** * Test for when the owner tries to delete their membership diff --git a/tests/e2e/Services/Teams/TeamsBaseServer.php b/tests/e2e/Services/Teams/TeamsBaseServer.php index 6a1d05e9d4..0c6d85e276 100644 --- a/tests/e2e/Services/Teams/TeamsBaseServer.php +++ b/tests/e2e/Services/Teams/TeamsBaseServer.php @@ -175,16 +175,6 @@ trait TeamsBaseServer $userUid = $response['body']['userId']; $membershipUid = $response['body']['$id']; - // $response = $this->client->call(Client::METHOD_GET, '/users/'.$userUid, array_merge([ - // 'content-type' => 'application/json', - // 'x-appwrite-project' => $this->getProject()['$id'], - // ], $this->getHeaders()), []); - - // $this->assertEquals($userUid, $response['body']['$id']); - // $this->assertContains('team:'.$teamUid, $response['body']['roles']); - // $this->assertContains('team:'.$teamUid.'/admin', $response['body']['roles']); - // $this->assertContains('team:'.$teamUid.'/editor', $response['body']['roles']); - /** * Test for FAILURE */ @@ -199,7 +189,7 @@ trait TeamsBaseServer 'url' => 'http://localhost:5000/join-us#title' ]); - $this->assertEquals(409, $response['headers']['status-code']); + $this->assertEquals(409, $response['headers']['status-code']); // membership already created $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Teams/TeamsCustomClientTest.php b/tests/e2e/Services/Teams/TeamsCustomClientTest.php index 03cb1983f1..7286bb0827 100644 --- a/tests/e2e/Services/Teams/TeamsCustomClientTest.php +++ b/tests/e2e/Services/Teams/TeamsCustomClientTest.php @@ -83,6 +83,38 @@ class TeamsCustomClientTest extends Scope $this->assertNotEmpty($response['body']['memberships'][0]['userName']); $this->assertNotEmpty($response['body']['memberships'][0]['userEmail']); $this->assertArrayHasKey('mfa', $response['body']['memberships'][0]); + + /** + * Update project settings to show only MFA + */ + $response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $this->getProject()['$id'] . '/auth/memberships-privacy', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => 'console', + 'cookie' => 'a_session_console=' . $this->getRoot()['session'], + ]), [ + 'userName' => false, + 'userEmail' => false, + 'mfa' => true, + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + /** + * Test that sensitive fields are not shown + */ + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertIsInt($response['body']['total']); + $this->assertNotEmpty($response['body']['memberships'][0]['$id']); + + // Assert that sensitive fields are present + $this->assertEmpty($response['body']['memberships'][0]['userName']); + $this->assertEmpty($response['body']['memberships'][0]['userEmail']); + $this->assertArrayHasKey('mfa', $response['body']['memberships'][0]); } /** diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index bd0a8ef937..00e999672f 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -310,6 +310,22 @@ trait UsersBase $this->assertNotEmpty($session['secret']); $this->assertNotEmpty($session['expire']); $this->assertEquals('server', $session['provider']); + + $response = $this->client->call(Client::METHOD_GET, '/account', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-session' => $session['secret'] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/current', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-session' => $session['secret'] + ]); + + $this->assertEquals(204, $response['headers']['status-code']); } @@ -785,6 +801,97 @@ trait UsersBase return $data; } + /** + * @depends testGetUser + */ + public function testListUserMemberships(array $data): array + { + /** + * Test for SUCCESS + */ + + // create a new team + $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'teamId' => 'unique()', + 'name' => 'Test Team', + ]); + + // create a new membership + $membership = $this->client->call(Client::METHOD_POST, '/teams/' . $team['body']['$id'] . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'userId' => $data['userId'], + 'roles' => ['new-role'], + ]); + + // list the memberships + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertEquals($response['body']['memberships'][0]['$id'], $membership['body']['$id']); + $this->assertEquals($response['body']['memberships'][0]['roles'], ['new-role']); + $this->assertEquals($response['body']['total'], 1); + + // create another membership with a new role + $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'teamId' => 'unique()', + 'name' => 'Test Team 2', + ]); + + $membership = $this->client->call(Client::METHOD_POST, '/teams/' . $team['body']['$id'] . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'userId' => $data['userId'], + 'roles' => ['new-role-2'], + ]); + + // list out memberships and query by role + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::contains('roles', ['new-role-2'])->toString() + ] + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertEquals($response['body']['memberships'][0]['$id'], $membership['body']['$id']); + $this->assertEquals($response['body']['memberships'][0]['roles'], ['new-role-2']); + $this->assertEquals($response['body']['total'], 1); + + /** + * Test for FAILURE + */ + + // query using equal on array field + $response = $this->client->call(Client::METHOD_GET, '/users/' . $data['userId'] . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('roles', ['new-role-2'])->toString() + ] + ]); + + $this->assertEquals($response['body']['code'], 400); + $this->assertEquals($response['body']['message'], 'Invalid `queries` param: Invalid query: Cannot query equal on attribute "roles" because it is an array.'); + $this->assertEquals($response['body']['type'], 'general_argument_invalid'); + + return $data; + } + /** * @depends testGetUser */ diff --git a/tests/e2e/Services/VCS/VCSConsoleClientTest.php b/tests/e2e/Services/VCS/VCSConsoleClientTest.php index f04667a0f5..13c3ddb251 100644 --- a/tests/e2e/Services/VCS/VCSConsoleClientTest.php +++ b/tests/e2e/Services/VCS/VCSConsoleClientTest.php @@ -22,6 +22,8 @@ class VCSConsoleClientTest extends Scope public string $providerInstallationId = '42954928'; // appwrite-test public string $providerRepositoryId = '705764267'; // ruby-starter (public) public string $providerRepositoryId2 = '708688544'; // function1.4 (private) + public string $providerRepositoryId3 = '943139433'; // svelte-starter (public) + public string $providerRepositoryId4 = '943245292'; // templates-for-sites (public) public function testGitHubAuthorize(): string { @@ -67,24 +69,102 @@ class VCSConsoleClientTest extends Scope * Test for SUCCESS */ - $runtime = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/providerRepositories/' . $this->providerRepositoryId . '/detection', array_merge([ + $runtime = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/detections', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + 'content-type' => 'application/json', + ], $this->getHeaders()), [ + 'providerRepositoryId' => $this->providerRepositoryId, + 'type' => 'runtime', + ]); $this->assertEquals(200, $runtime['headers']['status-code']); - $this->assertEquals($runtime['body']['runtime'], 'ruby-3.1'); + $this->assertEquals($runtime['body']['runtime'], 'ruby-3.3'); + $this->assertEquals($runtime['body']['commands'], 'bundle install && bundle exec rake build'); + $this->assertEquals($runtime['body']['entrypoint'], 'main.rb'); /** * Test for FAILURE */ - $runtime = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/providerRepositories/randomRepositoryId/detection', array_merge([ + $runtime = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/detections', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + 'content-type' => 'application/json', + ], $this->getHeaders()), [ + 'providerRepositoryId' => 'randomRepositoryId', // Invalid repository ID + 'type' => 'runtime', + ]); $this->assertEquals(404, $runtime['headers']['status-code']); } + /** + * @depends testGitHubAuthorize + */ + public function testDetectFramework(string $installationId) + { + /** + * Test for SUCCESS + */ + + $framework = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/detections', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + ], $this->getHeaders()), [ + 'providerRepositoryId' => $this->providerRepositoryId3, + 'type' => 'framework', + ]); + + $this->assertEquals(200, $framework['headers']['status-code']); + $this->assertEquals($framework['body']['framework'], 'sveltekit'); + $this->assertEquals($framework['body']['installCommand'], 'npm install'); + $this->assertEquals($framework['body']['buildCommand'], 'npm run build'); + $this->assertEquals($framework['body']['outputDirectory'], './build'); + + $framework = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/detections', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + ], $this->getHeaders()), [ + 'providerRepositoryId' => $this->providerRepositoryId4, + 'type' => 'framework', + 'providerRootDirectory' => 'astro/starter' + ]); + + $this->assertEquals(200, $framework['headers']['status-code']); + $this->assertEquals($framework['body']['framework'], 'astro'); + $this->assertEquals($framework['body']['installCommand'], 'npm install'); + $this->assertEquals($framework['body']['buildCommand'], 'npm run build'); + $this->assertEquals($framework['body']['outputDirectory'], './dist'); + + $framework = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/detections', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + ], $this->getHeaders()), [ + 'providerRepositoryId' => $this->providerRepositoryId4, + 'type' => 'framework', + 'providerRootDirectory' => 'remix/starter' + ]); + + $this->assertEquals(200, $framework['headers']['status-code']); + $this->assertEquals($framework['body']['framework'], 'remix'); + $this->assertEquals($framework['body']['installCommand'], 'npm install'); + $this->assertEquals($framework['body']['buildCommand'], 'npm run build'); + $this->assertEquals($framework['body']['outputDirectory'], './build'); + + /** + * Test for FAILURE + */ + + $framework = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/detections', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + 'content-type' => 'application/json', + ], $this->getHeaders()), [ + 'providerRepositoryId' => 'randomRepositoryId', // Invalid repository ID + 'type' => 'framework', + ]); + + $this->assertEquals(404, $framework['headers']['status-code']); + } + /** * @depends testGitHubAuthorize */ @@ -94,7 +174,7 @@ class VCSConsoleClientTest extends Scope * Test for SUCCESS */ - $runtime = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/providerRepositories/' . $this->providerRepositoryId . '/contents', array_merge([ + $runtime = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories/' . $this->providerRepositoryId . '/contents', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -126,7 +206,7 @@ class VCSConsoleClientTest extends Scope $this->assertTrue($libContent['isDirectory']); $this->assertEquals(0, $gemfileContent['size']); - $runtime = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/providerRepositories/' . $this->providerRepositoryId . '/contents?providerRootDirectory=lib', array_merge([ + $runtime = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories/' . $this->providerRepositoryId . '/contents?providerRootDirectory=lib', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -150,7 +230,7 @@ class VCSConsoleClientTest extends Scope * Test for FAILURE */ - $runtime = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/providerRepositories/randomRepositoryId/contents', array_merge([ + $runtime = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories/randomRepositoryId/contents', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); @@ -168,26 +248,75 @@ class VCSConsoleClientTest extends Scope $repositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ], $this->getHeaders()), [ + 'type' => 'runtime' + ]); $this->assertEquals(200, $repositories['headers']['status-code']); - $this->assertEquals($repositories['body']['total'], 3); - $this->assertEquals($repositories['body']['providerRepositories'][0]['name'], 'function1.4'); - $this->assertEquals($repositories['body']['providerRepositories'][0]['organization'], 'appwrite-test'); - $this->assertEquals($repositories['body']['providerRepositories'][0]['provider'], 'github'); - $this->assertEquals($repositories['body']['providerRepositories'][1]['name'], 'appwrite'); - $this->assertEquals($repositories['body']['providerRepositories'][2]['name'], 'ruby-starter'); - + $this->assertEquals($repositories['body']['total'], 4); + $this->assertEquals($repositories['body']['runtimeProviderRepositories'][0]['name'], 'starter-for-svelte'); + $this->assertEquals($repositories['body']['runtimeProviderRepositories'][0]['organization'], 'appwrite-test'); + $this->assertEquals($repositories['body']['runtimeProviderRepositories'][0]['provider'], 'github'); + $this->assertEquals($repositories['body']['runtimeProviderRepositories'][0]['runtime'], 'node-22'); $searchedRepositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'search' => 'func' + 'search' => 'function1.4', + 'type' => 'runtime' ]); - $this->assertEquals(200, $searchedRepositories['headers']['status-code']); $this->assertEquals($searchedRepositories['body']['total'], 1); - $this->assertEquals($searchedRepositories['body']['providerRepositories'][0]['name'], 'function1.4'); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['name'], 'function1.4'); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['runtime'], 'node-2'); + + $searchedRepositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'appwrite', + 'type' => 'runtime' + ]); + $this->assertEquals(200, $searchedRepositories['headers']['status-code']); + $this->assertEquals($searchedRepositories['body']['total'], 1); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['name'], 'appwrite'); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['runtime'], 'php-8.3'); + + $searchedRepositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'ruby-starter', + 'type' => 'runtime' + ]); + $this->assertEquals(200, $searchedRepositories['headers']['status-code']); + $this->assertEquals($searchedRepositories['body']['total'], 1); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['name'], 'ruby-starter'); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['runtime'], 'ruby-3.3'); + + $repositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'type' => 'framework' + ]); + + $this->assertEquals(200, $repositories['headers']['status-code']); + $this->assertEquals($repositories['body']['total'], 4); + $this->assertEquals($repositories['body']['frameworkProviderRepositories'][0]['name'], 'starter-for-svelte'); + $this->assertEquals($repositories['body']['frameworkProviderRepositories'][0]['organization'], 'appwrite-test'); + $this->assertEquals($repositories['body']['frameworkProviderRepositories'][0]['provider'], 'github'); + $this->assertEquals($repositories['body']['frameworkProviderRepositories'][0]['framework'], 'sveltekit'); + + $searchedRepositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'appwrite', + 'type' => 'runtime' + ]); + $this->assertEquals(200, $searchedRepositories['headers']['status-code']); + $this->assertEquals($searchedRepositories['body']['total'], 1); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['name'], 'appwrite'); + $this->assertEquals($searchedRepositories['body']['runtimeProviderRepositories'][0]['runtime'], 'other'); + + // TODO: If you are about to add another check, rewrite this to @provideScenarios /** * Test for FAILURE @@ -195,9 +324,29 @@ class VCSConsoleClientTest extends Scope $repositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/randomInstallationId/providerRepositories', array_merge([ 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ], $this->getHeaders()), [ + 'type' => 'runtime' + ]); $this->assertEquals(404, $repositories['headers']['status-code']); + + $repositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'type' => 'randomType' + ]); + + $this->assertEquals(400, $repositories['headers']['status-code']); + + $repositories = $this->client->call(Client::METHOD_GET, '/vcs/github/installations/' . $installationId . '/providerRepositories', array_merge([ + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'search' => 'randomSearch', + 'type' => 'framework' + ]); + + $this->assertEquals(200, $repositories['headers']['status-code']); + $this->assertEquals($repositories['body']['total'], 0); } /** diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index 2ef41003ee..c743810feb 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\Webhooks; +use Appwrite\Tests\Async; use Appwrite\Tests\Retry; use CURLFile; use Tests\E2E\Client; @@ -12,29 +13,20 @@ use Utopia\Database\Validator\Datetime as DatetimeValidator; trait WebhooksBase { - protected function awaitDeploymentIsBuilt($functionId, $deploymentId, $checkForSuccess = true): void + use Async; + + protected function awaitDeploymentIsBuilt($functionId, $deploymentId): void { - while (true) { + $this->assertEventually(function () use ($functionId, $deploymentId) { $deployment = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/deployments/' . $deploymentId, [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ]); - if ( - $deployment['headers']['status-code'] >= 400 - || \in_array($deployment['body']['status'], ['ready', 'failed']) - ) { - break; - } - - \sleep(1); - } - - if ($checkForSuccess) { $this->assertEquals(200, $deployment['headers']['status-code']); $this->assertEquals('ready', $deployment['body']['status'], \json_encode($deployment['body'])); - } + }); } public static function getWebhookSignature(array $webhook, string $signatureKey): string diff --git a/tests/resources/csv/documents.csv b/tests/resources/csv/documents.csv new file mode 100644 index 0000000000..ea1e33b5bd --- /dev/null +++ b/tests/resources/csv/documents.csv @@ -0,0 +1,101 @@ +$id,name,age +hxfcwpcas5xokpwe,Diamond Mendez,56 +gw8nxwf6esn3tfwf,Michael Huff,20 +xb6bxg56lral1qy9,Alyssa Rodriguez,37 +imerjq5j36y3agh2,Barbara Smith,26 +07yq9qdlhmbzmr35,Evelyn Edwards,54 +ksqo631sbhwj5ltg,Tina Richardson,41 +j7zlndgu0gbshp15,Joel Hernandez,49 +mfntvnljrcmf7h6v,Zachary Cooper,59 +5f9b01nziqu2h8ed,Brittany Spears,20 +4vxzbnzraqznk5u8,Holly White,47 +d4ywy3mtphaatbpf,Kimberly Barnes,27 +88odnk6nthyyvbal,Stephen Miller,53 +08oekee3fn7mzaa5,Yvonne Newman,41 +quw55kn9895i5e4v,Carol Kane,38 +nge6bm8ykripei6f,Doris Foster,44 +4k16i33s0xl2ypx9,Joseph Stokes,28 +q0j5rxbgid66snyf,Steve Williams,31 +n1oxun7mqq3p103y,James Carey,29 +0dbvs840jkf8i0ye,Kathryn Henry,38 +5sfaidgs1h87v15v,Christopher Landry,23 +vg3punvfu5khmf41,Jennifer Mcgee,62 +f933qydr9u5b2r11,Cathy Church,35 +wjv87y1inf8yk32s,Jose Lopez,41 +uljysdvdlcyrbrwk,William Rose,30 +ot8xtzh77j55wq0s,Sarah Ford,26 +9t76vnsv2u36s43t,Alisha Jones,61 +66y4tnty62hw8c02,Kristin Kelly,61 +2punfblazi5v16ar,Brendan Stout,40 +sxhr4nf5w2gx4wbg,Kelly Cruz,18 +68dvrqfwqnkq5el9,Samantha Martin,50 +20192l6dbeinhkh0,David Santos,46 +si0l4dgay09ebfmf,Elizabeth Carroll,22 +lhse40vbldqb6ap1,Corey Owens,46 +h5t3pslykyx3kxfm,Shelby Mueller,65 +ldc0luydrw6jub0f,Dr. Sylvia Myers,29 +voc9628xg4dsgw2y,Scott Freeman,48 +o4y0gk3gqv1ax2fz,Christopher Atkinson,21 +u1n3x4e4u7e0vzj6,Sean Diaz,31 +s36eskwtm0w7lwr7,Bobby Dyer,57 +4hjnag1p5iwvtixd,Daniel Hall,62 +m91d80oxsa216zbh,Jennifer Ramirez,65 +5hj6858zo2g85n6v,Angela Jackson,57 +8m8oihv9a1e7nn92,Kelly Lewis,36 +7azy39la0no0mxi7,Jessica Munoz,55 +47pmjkhnnqhyit8c,Kelly George,65 +6j6cpy4kgneg1mmh,Anthony Johnson,65 +tnlmtvap1zz89km9,Regina Fields,61 +6cyuvnwwqdmrpfzh,Sharon Schaefer,30 +p1v4pyu2pqodc0ey,Jacob French,62 +6npynnhjt2jd05xo,Jessica Costa,23 +wcxedf13n2e9qi4l,George Hardy,53 +yf2xlcmszk2tqeig,Andrea Allison,20 +3bf2zzv7poststwa,Kevin Ferguson,32 +c2iataz0hhv39q63,Joseph Johnson,58 +3e8npxhov4a39pvq,Ashley Martinez,18 +t7dp41tysipytywq,Charles Nixon,23 +z8cztq7c47phyfhk,Carol Dudley,40 +2636f9d8r4ipm3h6,David Weber,51 +eh3f6wxtvkjq6ykq,Scott Robinson,32 +raskbwpsje69a59h,Anthony Hardy,38 +90hn1p0b4cs9e2og,Mackenzie Owens,52 +am3swwfbo076x0v1,Brian Foster,27 +5uw7utb9lq5cfncw,Hannah Forbes,56 +cs6mbfzkzifefx6r,Lauren Reed,26 +ftw3uvztziiz9x00,Morgan Smith,28 +uhrqseeo43mozpaq,Samantha Alexander,65 +pvvmzyfc1lxor11e,Tiffany Roberts,20 +jia7bdag4abz123s,Emily Hayes,34 +h6oozcngbz8o5x4y,Rebecca Villegas,52 +9v6z1pn2f9twcy12,Donald Shah,61 +wzz3jduioso77o7f,Denise Cain,59 +u51plhgvjodkswnr,Kristine Ramirez,53 +t1uhkmiytfyc13vc,Stacey Adkins,61 +iqaqnf0ybg2ct507,Daniel Hunt,20 +idwrwv2uu4hcpv2i,Roberta Johnson,48 +2yd2hd6auetjacyo,Jason Williamson,39 +egrmdbibnjhi914x,Sandra Robinson,50 +15m1pz2bb0ercgyk,Steve Rice,25 +0i21bhkxdagjurb7,Kimberly Fritz,53 +726ofi7h5snreq67,Brianna Reynolds,33 +csqxse3wym56eim6,Alexander Williams,50 +qeaoylnrsf8p3byg,Andrew Thomas,25 +edsswobumzyzbvhf,Austin Williams,57 +hdzhzpt0ahy5hkib,Nicholas Williams,24 +w1qmvmg4roa8xnwu,Mrs. Michelle Cisneros,48 +3z3o73x7adyuo6w0,Stacey Smith,39 +sse2u5zlgoqrgmcf,Laura Beck,20 +rvovijmvch58r4yx,Molly Clark,51 +doe06nrx8sg5mcuv,Carmen Morris,41 +jbjdwuvj5s4kw04y,Amanda Munoz,20 +6k2ewkla7js0yw23,Rachel Collins,44 +fcxuyr4kkhrnigu1,John Alexander,18 +d25fuwlos5mk07o0,Stacy Hunter,22 +1vdai2rxmwd57oet,Eric Massey,40 +pq4jnt9izu1wlrzd,Scott Garcia,20 +lz9kfc0lty5xcz14,Cassandra Nelson,35 +pu7w6tyab5jd4we9,Aaron Johnson,50 +8dupswd2kqwdyn8v,Shannon Sherman,45 +ye466l71jthiz2p6,April Garcia,60 +xogsmfwb73l16qdt,Evan Lynn,20 diff --git a/tests/resources/csv/irrelevant-column.csv b/tests/resources/csv/irrelevant-column.csv new file mode 100644 index 0000000000..92105ceaa2 --- /dev/null +++ b/tests/resources/csv/irrelevant-column.csv @@ -0,0 +1,101 @@ +$id,name,age,email +hxfcwpcas5xokpwe,Diamond Mendez,56,diamond.mendez@example.com +gw8nxwf6esn3tfwf,Michael Huff,20,michael.huff@example.com +xb6bxg56lral1qy9,Alyssa Rodriguez,37,alyssa.rodriguez@example.com +imerjq5j36y3agh2,Barbara Smith,26,barbara.smith@example.com +07yq9qdlhmbzmr35,Evelyn Edwards,54,evelyn.edwards@example.com +ksqo631sbhwj5ltg,Tina Richardson,41,tina.richardson@example.com +j7zlndgu0gbshp15,Joel Hernandez,49,joel.hernandez@example.com +mfntvnljrcmf7h6v,Zachary Cooper,59,zachary.cooper@example.com +5f9b01nziqu2h8ed,Brittany Spears,20,brittany.spears@example.com +4vxzbnzraqznk5u8,Holly White,47,holly.white@example.com +d4ywy3mtphaatbpf,Kimberly Barnes,27,kimberly.barnes@example.com +88odnk6nthyyvbal,Stephen Miller,53,stephen.miller@example.com +08oekee3fn7mzaa5,Yvonne Newman,41,yvonne.newman@example.com +quw55kn9895i5e4v,Carol Kane,38,carol.kane@example.com +nge6bm8ykripei6f,Doris Foster,44,doris.foster@example.com +4k16i33s0xl2ypx9,Joseph Stokes,28,joseph.stokes@example.com +q0j5rxbgid66snyf,Steve Williams,31,steve.williams@example.com +n1oxun7mqq3p103y,James Carey,29,james.carey@example.com +0dbvs840jkf8i0ye,Kathryn Henry,38,kathryn.henry@example.com +5sfaidgs1h87v15v,Christopher Landry,23,christopher.landry@example.com +vg3punvfu5khmf41,Jennifer Mcgee,62,jennifer.mcgee@example.com +f933qydr9u5b2r11,Cathy Church,35,cathy.church@example.com +wjv87y1inf8yk32s,Jose Lopez,41,jose.lopez@example.com +uljysdvdlcyrbrwk,William Rose,30,william.rose@example.com +ot8xtzh77j55wq0s,Sarah Ford,26,sarah.ford@example.com +9t76vnsv2u36s43t,Alisha Jones,61,alisha.jones@example.com +66y4tnty62hw8c02,Kristin Kelly,61,kristin.kelly@example.com +2punfblazi5v16ar,Brendan Stout,40,brendan.stout@example.com +sxhr4nf5w2gx4wbg,Kelly Cruz,18,kelly.cruz@example.com +68dvrqfwqnkq5el9,Samantha Martin,50,samantha.martin@example.com +20192l6dbeinhkh0,David Santos,46,david.santos@example.com +si0l4dgay09ebfmf,Elizabeth Carroll,22,elizabeth.carroll@example.com +lhse40vbldqb6ap1,Corey Owens,46,corey.owens@example.com +h5t3pslykyx3kxfm,Shelby Mueller,65,shelby.mueller@example.com +ldc0luydrw6jub0f,Dr. Sylvia Myers,29,sylvia.myers@example.com +voc9628xg4dsgw2y,Scott Freeman,48,scott.freeman@example.com +o4y0gk3gqv1ax2fz,Christopher Atkinson,21,christopher.atkinson@example.com +u1n3x4e4u7e0vzj6,Sean Diaz,31,sean.diaz@example.com +s36eskwtm0w7lwr7,Bobby Dyer,57,bobby.dyer@example.com +4hjnag1p5iwvtixd,Daniel Hall,62,daniel.hall@example.com +m91d80oxsa216zbh,Jennifer Ramirez,65,jennifer.ramirez@example.com +5hj6858zo2g85n6v,Angela Jackson,57,angela.jackson@example.com +8m8oihv9a1e7nn92,Kelly Lewis,36,kelly.lewis@example.com +7azy39la0no0mxi7,Jessica Munoz,55,jessica.munoz@example.com +47pmjkhnnqhyit8c,Kelly George,65,kelly.george@example.com +6j6cpy4kgneg1mmh,Anthony Johnson,65,anthony.johnson@example.com +tnlmtvap1zz89km9,Regina Fields,61,regina.fields@example.com +6cyuvnwwqdmrpfzh,Sharon Schaefer,30,sharon.schaefer@example.com +p1v4pyu2pqodc0ey,Jacob French,62,jacob.french@example.com +6npynnhjt2jd05xo,Jessica Costa,23,jessica.costa@example.com +wcxedf13n2e9qi4l,George Hardy,53,george.hardy@example.com +yf2xlcmszk2tqeig,Andrea Allison,20,andrea.allison@example.com +3bf2zzv7poststwa,Kevin Ferguson,32,kevin.ferguson@example.com +c2iataz0hhv39q63,Joseph Johnson,58,joseph.johnson@example.com +3e8npxhov4a39pvq,Ashley Martinez,18,ashley.martinez@example.com +t7dp41tysipytywq,Charles Nixon,23,charles.nixon@example.com +z8cztq7c47phyfhk,Carol Dudley,40,carol.dudley@example.com +2636f9d8r4ipm3h6,David Weber,51,david.weber@example.com +eh3f6wxtvkjq6ykq,Scott Robinson,32,scott.robinson@example.com +raskbwpsje69a59h,Anthony Hardy,38,anthony.hardy@example.com +90hn1p0b4cs9e2og,Mackenzie Owens,52,mackenzie.owens@example.com +am3swwfbo076x0v1,Brian Foster,27,brian.foster@example.com +5uw7utb9lq5cfncw,Hannah Forbes,56,hannah.forbes@example.com +cs6mbfzkzifefx6r,Lauren Reed,26,lauren.reed@example.com +ftw3uvztziiz9x00,Morgan Smith,28,morgan.smith@example.com +uhrqseeo43mozpaq,Samantha Alexander,65,samantha.alexander@example.com +pvvmzyfc1lxor11e,Tiffany Roberts,20,tiffany.roberts@example.com +jia7bdag4abz123s,Emily Hayes,34,emily.hayes@example.com +h6oozcngbz8o5x4y,Rebecca Villegas,52,rebecca.villegas@example.com +9v6z1pn2f9twcy12,Donald Shah,61,donald.shah@example.com +wzz3jduioso77o7f,Denise Cain,59,denise.cain@example.com +u51plhgvjodkswnr,Kristine Ramirez,53,kristine.ramirez@example.com +t1uhkmiytfyc13vc,Stacey Adkins,61,stacey.adkins@example.com +iqaqnf0ybg2ct507,Daniel Hunt,20,daniel.hunt@example.com +idwrwv2uu4hcpv2i,Roberta Johnson,48,roberta.johnson@example.com +2yd2hd6auetjacyo,Jason Williamson,39,jason.williamson@example.com +egrmdbibnjhi914x,Sandra Robinson,50,sandra.robinson@example.com +15m1pz2bb0ercgyk,Steve Rice,25,steve.rice@example.com +0i21bhkxdagjurb7,Kimberly Fritz,53,kimberly.fritz@example.com +726ofi7h5snreq67,Brianna Reynolds,33,brianna.reynolds@example.com +csqxse3wym56eim6,Alexander Williams,50,alexander.williams@example.com +qeaoylnrsf8p3byg,Andrew Thomas,25,andrew.thomas@example.com +edsswobumzyzbvhf,Austin Williams,57,austin.williams@example.com +hdzhzpt0ahy5hkib,Nicholas Williams,24,nicholas.williams@example.com +w1qmvmg4roa8xnwu,Mrs. Michelle Cisneros,48,michelle.cisneros@example.com +3z3o73x7adyuo6w0,Stacey Smith,39,stacey.smith@example.com +sse2u5zlgoqrgmcf,Laura Beck,20,laura.beck@example.com +rvovijmvch58r4yx,Molly Clark,51,molly.clark@example.com +doe06nrx8sg5mcuv,Carmen Morris,41,carmen.morris@example.com +jbjdwuvj5s4kw04y,Amanda Munoz,20,amanda.munoz@example.com +6k2ewkla7js0yw23,Rachel Collins,44,rachel.collins@example.com +fcxuyr4kkhrnigu1,John Alexander,18,john.alexander@example.com +d25fuwlos5mk07o0,Stacy Hunter,22,stacy.hunter@example.com +1vdai2rxmwd57oet,Eric Massey,40,eric.massey@example.com +pq4jnt9izu1wlrzd,Scott Garcia,20,scott.garcia@example.com +lz9kfc0lty5xcz14,Cassandra Nelson,35,cassandra.nelson@example.com +pu7w6tyab5jd4we9,Aaron Johnson,50,aaron.johnson@example.com +8dupswd2kqwdyn8v,Shannon Sherman,45,shannon.sherman@example.com +ye466l71jthiz2p6,April Garcia,60,april.garcia@example.com +xogsmfwb73l16qdt,Evan Lynn,20,evan.lynn@example.com diff --git a/tests/resources/csv/missing-column.csv b/tests/resources/csv/missing-column.csv new file mode 100644 index 0000000000..e57b5ccb2e --- /dev/null +++ b/tests/resources/csv/missing-column.csv @@ -0,0 +1,101 @@ +$id,name +hxfcwpcas5xokpwe,Diamond Mendez +gw8nxwf6esn3tfwf,Michael Huff +xb6bxg56lral1qy9,Alyssa Rodriguez +imerjq5j36y3agh2,Barbara Smith +07yq9qdlhmbzmr35,Evelyn Edwards +ksqo631sbhwj5ltg,Tina Richardson +j7zlndgu0gbshp15,Joel Hernandez +mfntvnljrcmf7h6v,Zachary Cooper +5f9b01nziqu2h8ed,Brittany Spears +4vxzbnzraqznk5u8,Holly White +d4ywy3mtphaatbpf,Kimberly Barnes +88odnk6nthyyvbal,Stephen Miller +08oekee3fn7mzaa5,Yvonne Newman +quw55kn9895i5e4v,Carol Kane +nge6bm8ykripei6f,Doris Foster +4k16i33s0xl2ypx9,Joseph Stokes +q0j5rxbgid66snyf,Steve Williams +n1oxun7mqq3p103y,James Carey +0dbvs840jkf8i0ye,Kathryn Henry +5sfaidgs1h87v15v,Christopher Landry +vg3punvfu5khmf41,Jennifer Mcgee +f933qydr9u5b2r11,Cathy Church +wjv87y1inf8yk32s,Jose Lopez +uljysdvdlcyrbrwk,William Rose +ot8xtzh77j55wq0s,Sarah Ford +9t76vnsv2u36s43t,Alisha Jones +66y4tnty62hw8c02,Kristin Kelly +2punfblazi5v16ar,Brendan Stout +sxhr4nf5w2gx4wbg,Kelly Cruz +68dvrqfwqnkq5el9,Samantha Martin +20192l6dbeinhkh0,David Santos +si0l4dgay09ebfmf,Elizabeth Carroll +lhse40vbldqb6ap1,Corey Owens +h5t3pslykyx3kxfm,Shelby Mueller +ldc0luydrw6jub0f,Dr. Sylvia Myers +voc9628xg4dsgw2y,Scott Freeman +o4y0gk3gqv1ax2fz,Christopher Atkinson +u1n3x4e4u7e0vzj6,Sean Diaz +s36eskwtm0w7lwr7,Bobby Dyer +4hjnag1p5iwvtixd,Daniel Hall +m91d80oxsa216zbh,Jennifer Ramirez +5hj6858zo2g85n6v,Angela Jackson +8m8oihv9a1e7nn92,Kelly Lewis +7azy39la0no0mxi7,Jessica Munoz +47pmjkhnnqhyit8c,Kelly George +6j6cpy4kgneg1mmh,Anthony Johnson +tnlmtvap1zz89km9,Regina Fields +6cyuvnwwqdmrpfzh,Sharon Schaefer +p1v4pyu2pqodc0ey,Jacob French +6npynnhjt2jd05xo,Jessica Costa +wcxedf13n2e9qi4l,George Hardy +yf2xlcmszk2tqeig,Andrea Allison +3bf2zzv7poststwa,Kevin Ferguson +c2iataz0hhv39q63,Joseph Johnson +3e8npxhov4a39pvq,Ashley Martinez +t7dp41tysipytywq,Charles Nixon +z8cztq7c47phyfhk,Carol Dudley +2636f9d8r4ipm3h6,David Weber +eh3f6wxtvkjq6ykq,Scott Robinson +raskbwpsje69a59h,Anthony Hardy +90hn1p0b4cs9e2og,Mackenzie Owens +am3swwfbo076x0v1,Brian Foster +5uw7utb9lq5cfncw,Hannah Forbes +cs6mbfzkzifefx6r,Lauren Reed +ftw3uvztziiz9x00,Morgan Smith +uhrqseeo43mozpaq,Samantha Alexander +pvvmzyfc1lxor11e,Tiffany Roberts +jia7bdag4abz123s,Emily Hayes +h6oozcngbz8o5x4y,Rebecca Villegas +9v6z1pn2f9twcy12,Donald Shah +wzz3jduioso77o7f,Denise Cain +u51plhgvjodkswnr,Kristine Ramirez +t1uhkmiytfyc13vc,Stacey Adkins +iqaqnf0ybg2ct507,Daniel Hunt +idwrwv2uu4hcpv2i,Roberta Johnson +2yd2hd6auetjacyo,Jason Williamson +egrmdbibnjhi914x,Sandra Robinson +15m1pz2bb0ercgyk,Steve Rice +0i21bhkxdagjurb7,Kimberly Fritz +726ofi7h5snreq67,Brianna Reynolds +csqxse3wym56eim6,Alexander Williams +qeaoylnrsf8p3byg,Andrew Thomas +edsswobumzyzbvhf,Austin Williams +hdzhzpt0ahy5hkib,Nicholas Williams +w1qmvmg4roa8xnwu,Mrs. Michelle Cisneros +3z3o73x7adyuo6w0,Stacey Smith +sse2u5zlgoqrgmcf,Laura Beck +rvovijmvch58r4yx,Molly Clark +doe06nrx8sg5mcuv,Carmen Morris +jbjdwuvj5s4kw04y,Amanda Munoz +6k2ewkla7js0yw23,Rachel Collins +fcxuyr4kkhrnigu1,John Alexander +d25fuwlos5mk07o0,Stacy Hunter +1vdai2rxmwd57oet,Eric Massey +pq4jnt9izu1wlrzd,Scott Garcia +lz9kfc0lty5xcz14,Cassandra Nelson +pu7w6tyab5jd4we9,Aaron Johnson +8dupswd2kqwdyn8v,Shannon Sherman +ye466l71jthiz2p6,April Garcia +xogsmfwb73l16qdt,Evan Lynn diff --git a/tests/resources/csv/missing-row.csv b/tests/resources/csv/missing-row.csv new file mode 100644 index 0000000000..7399fa9f51 --- /dev/null +++ b/tests/resources/csv/missing-row.csv @@ -0,0 +1,101 @@ +$id,name,age +hxfcwpcas5xokpwe,Diamond Mendez +gw8nxwf6esn3tfwf,Michael Huff +xb6bxg56lral1qy9,Alyssa Rodriguez +imerjq5j36y3agh2,Barbara Smith +07yq9qdlhmbzmr35,Evelyn Edwards +ksqo631sbhwj5ltg,Tina Richardson +j7zlndgu0gbshp15,Joel Hernandez +mfntvnljrcmf7h6v,Zachary Cooper +5f9b01nziqu2h8ed,Brittany Spears +4vxzbnzraqznk5u8,Holly White +d4ywy3mtphaatbpf,Kimberly Barnes +88odnk6nthyyvbal,Stephen Miller +08oekee3fn7mzaa5,Yvonne Newman +quw55kn9895i5e4v,Carol Kane +nge6bm8ykripei6f,Doris Foster +4k16i33s0xl2ypx9,Joseph Stokes +q0j5rxbgid66snyf,Steve Williams +n1oxun7mqq3p103y,James Carey +0dbvs840jkf8i0ye,Kathryn Henry +5sfaidgs1h87v15v,Christopher Landry +vg3punvfu5khmf41,Jennifer Mcgee +f933qydr9u5b2r11,Cathy Church +wjv87y1inf8yk32s,Jose Lopez +uljysdvdlcyrbrwk,William Rose +ot8xtzh77j55wq0s,Sarah Ford +9t76vnsv2u36s43t,Alisha Jones +66y4tnty62hw8c02,Kristin Kelly +2punfblazi5v16ar,Brendan Stout +sxhr4nf5w2gx4wbg,Kelly Cruz +68dvrqfwqnkq5el9,Samantha Martin +20192l6dbeinhkh0,David Santos +si0l4dgay09ebfmf,Elizabeth Carroll +lhse40vbldqb6ap1,Corey Owens +h5t3pslykyx3kxfm,Shelby Mueller +ldc0luydrw6jub0f,Dr. Sylvia Myers +voc9628xg4dsgw2y,Scott Freeman +o4y0gk3gqv1ax2fz,Christopher Atkinson +u1n3x4e4u7e0vzj6,Sean Diaz +s36eskwtm0w7lwr7,Bobby Dyer +4hjnag1p5iwvtixd,Daniel Hall +m91d80oxsa216zbh,Jennifer Ramirez +5hj6858zo2g85n6v,Angela Jackson +8m8oihv9a1e7nn92,Kelly Lewis +7azy39la0no0mxi7,Jessica Munoz +47pmjkhnnqhyit8c,Kelly George +6j6cpy4kgneg1mmh,Anthony Johnson +tnlmtvap1zz89km9,Regina Fields +6cyuvnwwqdmrpfzh,Sharon Schaefer +p1v4pyu2pqodc0ey,Jacob French +6npynnhjt2jd05xo,Jessica Costa +wcxedf13n2e9qi4l,George Hardy +yf2xlcmszk2tqeig,Andrea Allison +3bf2zzv7poststwa,Kevin Ferguson +c2iataz0hhv39q63,Joseph Johnson +3e8npxhov4a39pvq,Ashley Martinez +t7dp41tysipytywq,Charles Nixon +z8cztq7c47phyfhk,Carol Dudley +2636f9d8r4ipm3h6,David Weber +eh3f6wxtvkjq6ykq,Scott Robinson +raskbwpsje69a59h,Anthony Hardy +90hn1p0b4cs9e2og,Mackenzie Owens +am3swwfbo076x0v1,Brian Foster +5uw7utb9lq5cfncw,Hannah Forbes +cs6mbfzkzifefx6r,Lauren Reed +ftw3uvztziiz9x00,Morgan Smith +uhrqseeo43mozpaq,Samantha Alexander +pvvmzyfc1lxor11e,Tiffany Roberts +jia7bdag4abz123s,Emily Hayes +h6oozcngbz8o5x4y,Rebecca Villegas +9v6z1pn2f9twcy12,Donald Shah +wzz3jduioso77o7f,Denise Cain +u51plhgvjodkswnr,Kristine Ramirez +t1uhkmiytfyc13vc,Stacey Adkins +iqaqnf0ybg2ct507,Daniel Hunt +idwrwv2uu4hcpv2i,Roberta Johnson +2yd2hd6auetjacyo,Jason Williamson +egrmdbibnjhi914x,Sandra Robinson +15m1pz2bb0ercgyk,Steve Rice +0i21bhkxdagjurb7,Kimberly Fritz +726ofi7h5snreq67,Brianna Reynolds +csqxse3wym56eim6,Alexander Williams +qeaoylnrsf8p3byg,Andrew Thomas +edsswobumzyzbvhf,Austin Williams +hdzhzpt0ahy5hkib,Nicholas Williams +w1qmvmg4roa8xnwu,Mrs. Michelle Cisneros +3z3o73x7adyuo6w0,Stacey Smith +sse2u5zlgoqrgmcf,Laura Beck +rvovijmvch58r4yx,Molly Clark +doe06nrx8sg5mcuv,Carmen Morris +jbjdwuvj5s4kw04y,Amanda Munoz +6k2ewkla7js0yw23,Rachel Collins +fcxuyr4kkhrnigu1,John Alexander +d25fuwlos5mk07o0,Stacy Hunter +1vdai2rxmwd57oet,Eric Massey +pq4jnt9izu1wlrzd,Scott Garcia +lz9kfc0lty5xcz14,Cassandra Nelson +pu7w6tyab5jd4we9,Aaron Johnson +8dupswd2kqwdyn8v,Shannon Sherman +ye466l71jthiz2p6,April Garcia +xogsmfwb73l16qdt,Evan Lynn diff --git a/tests/resources/docker/docker-compose.yml b/tests/resources/docker/docker-compose.yml index 94d506056c..4bbca3e9c0 100644 --- a/tests/resources/docker/docker-compose.yml +++ b/tests/resources/docker/docker-compose.yml @@ -67,7 +67,7 @@ services: - _APP_OPTIONS_ABUSE - _APP_OPTIONS_ROUTER_PROTECTION - _APP_OPTIONS_FORCE_HTTPS - - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS + - _APP_OPTIONS_ROUTER_FORCE_HTTPS - _APP_OPENSSL_KEY_V1 - _APP_DOMAIN - _APP_DOMAIN_FUNCTIONS @@ -83,15 +83,14 @@ services: - _APP_STORAGE_ANTIVIRUS=disabled - _APP_STORAGE_LIMIT - _APP_FUNCTIONS_TIMEOUT - - _APP_FUNCTIONS_CONTAINERS - - _APP_FUNCTIONS_CPUS - - _APP_FUNCTIONS_MEMORY - - _APP_FUNCTIONS_MEMORY_SWAP + - _APP_SITES_TIMEOUT + - _APP_COMPUTE_CPUS + - _APP_COMPUTE_MEMORY - _APP_EXECUTOR_HOST - appwrite-worker-usage: - entrypoint: worker-usage - container_name: appwrite-worker-usage + appwrite-worker-stats-usage: + entrypoint: worker-stats-usage + container_name: appwrite-worker-stats-usage build: context: . restart: unless-stopped @@ -241,10 +240,9 @@ services: - _APP_DB_USER - _APP_DB_PASS - _APP_FUNCTIONS_TIMEOUT - - _APP_FUNCTIONS_CONTAINERS - - _APP_FUNCTIONS_CPUS - - _APP_FUNCTIONS_MEMORY - - _APP_FUNCTIONS_MEMORY_SWAP + - _APP_SITES_TIMEOUT + - _APP_COMPUTE_CPUS + - _APP_COMPUTE_MEMORY - _APP_EXECUTOR_HOST appwrite-worker-mails: diff --git a/tests/resources/functions/node/index.js b/tests/resources/functions/node/index.js index 041e4a8c12..e8eb938a15 100644 --- a/tests/resources/functions/node/index.js +++ b/tests/resources/functions/node/index.js @@ -14,6 +14,8 @@ module.exports = async(context) => { 'APPWRITE_FUNCTION_USER_ID' : context.req.headers['x-appwrite-user-id'] ?? '', 'APPWRITE_FUNCTION_JWT' : context.req.headers['x-appwrite-user-jwt'] ?? '', 'APPWRITE_FUNCTION_PROJECT_ID' : process.env.APPWRITE_FUNCTION_PROJECT_ID, + 'APPWRITE_FUNCTION_MEMORY' : process.env.APPWRITE_FUNCTION_MEMORY, + 'APPWRITE_FUNCTION_CPUS' : process.env.APPWRITE_FUNCTION_CPUS, 'CUSTOM_VARIABLE' : process.env.CUSTOM_VARIABLE }); } \ No newline at end of file diff --git a/tests/resources/functions/node/maintenance.js b/tests/resources/functions/node/maintenance.js new file mode 100644 index 0000000000..0885f11041 --- /dev/null +++ b/tests/resources/functions/node/maintenance.js @@ -0,0 +1,3 @@ +module.exports = async(context) => { + return context.res.send('Maintenance'); +} \ No newline at end of file diff --git a/tests/resources/functions/php/index.php b/tests/resources/functions/php/index.php index 27a9418b3c..6c67f27ee1 100644 --- a/tests/resources/functions/php/index.php +++ b/tests/resources/functions/php/index.php @@ -1,6 +1,12 @@ <?php return function ($context) { + if ($context->req->path === '/custom-response') { + $code = (int) ($context->req->query['code'] ?? '200'); + $body = $context->req->query['body'] ?? ''; + return $context->res->send($body, $code); + } + $context->log('body-is-' . ($context->req->body ?? '')); $context->log('custom-header-is-' . ($context->req->headers['x-custom-header'] ?? '')); $context->log('method-is-' . \strtolower($context->req->method ?? '')); diff --git a/tests/resources/qr/qr-default.png b/tests/resources/qr/qr-default.png index 58af53bb93..467be60e07 100644 Binary files a/tests/resources/qr/qr-default.png and b/tests/resources/qr/qr-default.png differ diff --git a/tests/resources/qr/qr-size-200-margin-10.png b/tests/resources/qr/qr-size-200-margin-10.png index b40529396e..ed98698390 100644 Binary files a/tests/resources/qr/qr-size-200-margin-10.png and b/tests/resources/qr/qr-size-200-margin-10.png differ diff --git a/tests/resources/qr/qr-size-200.png b/tests/resources/qr/qr-size-200.png index a44e4861e3..f7418d548f 100644 Binary files a/tests/resources/qr/qr-size-200.png and b/tests/resources/qr/qr-size-200.png differ diff --git a/tests/resources/sites/astro-static/astro.config.mjs b/tests/resources/sites/astro-static/astro.config.mjs new file mode 100644 index 0000000000..20b0b8e2ba --- /dev/null +++ b/tests/resources/sites/astro-static/astro.config.mjs @@ -0,0 +1,4 @@ +import { defineConfig } from 'astro/config'; + +export default defineConfig({ +}); diff --git a/tests/resources/sites/astro-static/package.json b/tests/resources/sites/astro-static/package.json new file mode 100644 index 0000000000..147dcf1f07 --- /dev/null +++ b/tests/resources/sites/astro-static/package.json @@ -0,0 +1,14 @@ +{ + "name": "my-astro-app", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "astro": "^5.2.5" + } +} diff --git a/tests/resources/sites/astro-static/src/pages/index.astro b/tests/resources/sites/astro-static/src/pages/index.astro new file mode 100644 index 0000000000..0b4f43c3d6 --- /dev/null +++ b/tests/resources/sites/astro-static/src/pages/index.astro @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Astro static + + + + diff --git a/tests/resources/sites/astro/astro.config.mjs b/tests/resources/sites/astro/astro.config.mjs new file mode 100644 index 0000000000..a87942461e --- /dev/null +++ b/tests/resources/sites/astro/astro.config.mjs @@ -0,0 +1,9 @@ +import { defineConfig } from 'astro/config'; +import node from '@astrojs/node'; + +export default defineConfig({ + output: 'server', + adapter: node({ + mode: 'standalone' + }), +}); diff --git a/tests/resources/sites/astro/package.json b/tests/resources/sites/astro/package.json new file mode 100644 index 0000000000..8cbcb910f5 --- /dev/null +++ b/tests/resources/sites/astro/package.json @@ -0,0 +1,15 @@ +{ + "name": "my-astro-app", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/node": "^9.0.2", + "astro": "^5.2.5" + } +} diff --git a/tests/resources/sites/astro/src/pages/index.astro b/tests/resources/sites/astro/src/pages/index.astro new file mode 100644 index 0000000000..cc8fd9411f --- /dev/null +++ b/tests/resources/sites/astro/src/pages/index.astro @@ -0,0 +1,15 @@ +--- +const value = import.meta.env.name || 'Variable not found'; +--- + + + + + + + Astro SSR + + +

Env variable is {value}

+ + diff --git a/tests/resources/sites/astro/src/pages/logs-action.js b/tests/resources/sites/astro/src/pages/logs-action.js new file mode 100644 index 0000000000..348297a616 --- /dev/null +++ b/tests/resources/sites/astro/src/pages/logs-action.js @@ -0,0 +1,7 @@ +export async function GET(context) { + console.log("Log1"); + console.error("Error1"); + console.log("Log2"); + console.error("Error2"); + return new Response('Action logs printed.'); +} diff --git a/tests/resources/sites/astro/src/pages/logs-inline.astro b/tests/resources/sites/astro/src/pages/logs-inline.astro new file mode 100644 index 0000000000..c539142d83 --- /dev/null +++ b/tests/resources/sites/astro/src/pages/logs-inline.astro @@ -0,0 +1,18 @@ +--- +console.log("Log1"); +console.error("Error1"); +console.log("Log2"); +console.error("Error2"); +--- + + + + + + + Astro Logs + + +

Inline logs printed.

+ + diff --git a/tests/resources/sites/static-single-file/main.html b/tests/resources/sites/static-single-file/main.html new file mode 100644 index 0000000000..2615f0c820 --- /dev/null +++ b/tests/resources/sites/static-single-file/main.html @@ -0,0 +1,10 @@ + + + + + + Main page + + + + \ No newline at end of file diff --git a/tests/resources/sites/static-spa/404.html b/tests/resources/sites/static-spa/404.html new file mode 100644 index 0000000000..2a51f36d22 --- /dev/null +++ b/tests/resources/sites/static-spa/404.html @@ -0,0 +1,10 @@ + + + + + + + +

Customized 404 page

+ + diff --git a/tests/resources/sites/static-spa/contact.html b/tests/resources/sites/static-spa/contact.html new file mode 100644 index 0000000000..1ef7dc9497 --- /dev/null +++ b/tests/resources/sites/static-spa/contact.html @@ -0,0 +1,10 @@ + + + + + + + +

Contact page

+ + diff --git a/tests/resources/sites/static-spa/index.html b/tests/resources/sites/static-spa/index.html new file mode 100644 index 0000000000..3fd2262803 --- /dev/null +++ b/tests/resources/sites/static-spa/index.html @@ -0,0 +1,10 @@ + + + + + + + +

Index page

+ + diff --git a/tests/resources/sites/static-themed/index.html b/tests/resources/sites/static-themed/index.html new file mode 100644 index 0000000000..955696b473 --- /dev/null +++ b/tests/resources/sites/static-themed/index.html @@ -0,0 +1,23 @@ + + + + + + Themed website + + + + diff --git a/tests/resources/sites/static/contact.html b/tests/resources/sites/static/contact.html new file mode 100644 index 0000000000..b2c16fc471 --- /dev/null +++ b/tests/resources/sites/static/contact.html @@ -0,0 +1,11 @@ + + + + + + Contact page + + +

Contact page

+ + \ No newline at end of file diff --git a/tests/resources/sites/static/index.html b/tests/resources/sites/static/index.html new file mode 100644 index 0000000000..ca1b1cc78d --- /dev/null +++ b/tests/resources/sites/static/index.html @@ -0,0 +1,11 @@ + + + + + + Hello Appwrite + + +

Hello Appwrite

+ + \ No newline at end of file diff --git a/tests/resources/sites/sub-directories/index.html b/tests/resources/sites/sub-directories/index.html new file mode 100644 index 0000000000..d21a10191c --- /dev/null +++ b/tests/resources/sites/sub-directories/index.html @@ -0,0 +1,5 @@ + + +

Sub-directory index

+ + diff --git a/tests/resources/sites/sub-directories/project1/index.html b/tests/resources/sites/sub-directories/project1/index.html new file mode 100644 index 0000000000..8fc477991c --- /dev/null +++ b/tests/resources/sites/sub-directories/project1/index.html @@ -0,0 +1,5 @@ + + +

Sub-directory project1

+ + \ No newline at end of file diff --git a/tests/unit/Auth/KeyTest.php b/tests/unit/Auth/KeyTest.php new file mode 100644 index 0000000000..8ae2114697 --- /dev/null +++ b/tests/unit/Auth/KeyTest.php @@ -0,0 +1,56 @@ + $projectId,]); + $decoded = Key::decode($project, $key); + + $this->assertEquals($projectId, $decoded->getProjectId()); + $this->assertEquals(API_KEY_DYNAMIC, $decoded->getType()); + $this->assertEquals(Auth::USER_ROLE_APPS, $decoded->getRole()); + $this->assertEquals(\array_merge($scopes, $roleScopes), $decoded->getScopes()); + } + + private static function generateKey( + string $projectId, + bool $usage, + array $scopes, + ): string { + $jwt = new JWT( + key: System::getEnv('_APP_OPENSSL_KEY_V1'), + algo: 'HS256', + maxAge: 86400, + leeway: 0, + ); + + $apiKey = $jwt->encode([ + 'projectId' => $projectId, + 'usage' => $usage, + 'scopes' => $scopes, + ]); + + return API_KEY_DYNAMIC . '_' . $apiKey; + } +} diff --git a/tests/unit/Auth/Validator/PhoneTest.php b/tests/unit/Auth/Validator/PhoneTest.php index d5a4e7f826..b7730641c3 100644 --- a/tests/unit/Auth/Validator/PhoneTest.php +++ b/tests/unit/Auth/Validator/PhoneTest.php @@ -31,6 +31,7 @@ class PhoneTest extends TestCase $this->assertEquals($this->object->isValid('+0415553452342'), false); $this->assertEquals($this->object->isValid('+14 155 5524564'), false); $this->assertEquals($this->object->isValid('+1415555245634543'), false); + $this->assertEquals($this->object->isValid('+8020000000'), false); // when country code is not present $this->assertEquals($this->object->isValid(+14155552456), false); $this->assertEquals($this->object->isValid('+1415555'), true); diff --git a/tests/unit/Event/EventTest.php b/tests/unit/Event/EventTest.php index 079bb47b65..c852cf2757 100644 --- a/tests/unit/Event/EventTest.php +++ b/tests/unit/Event/EventTest.php @@ -5,7 +5,7 @@ namespace Tests\Unit\Event; use Appwrite\Event\Event; use InvalidArgumentException; use PHPUnit\Framework\TestCase; -use Utopia\Queue\Client; +use Utopia\Queue\Publisher; require_once __DIR__ . '/../../../app/init.php'; @@ -13,13 +13,14 @@ class EventTest extends TestCase { protected ?Event $object = null; protected string $queue = ''; + protected Publisher $publisher; public function setUp(): void { - global $register; - $connection = $register->get('pools')->get('queue')->pop()->getResource(); + $this->publisher = new MockPublisher(); + $this->queue = 'v1-tests' . uniqid(); - $this->object = new Event($connection); + $this->object = new Event($this->publisher); $this->object->setClass('TestsV1'); $this->object->setQueue($this->queue); } @@ -51,10 +52,7 @@ class EventTest extends TestCase $this->assertEquals('eventValue1', $this->object->getParam('eventKey1')); $this->assertEquals('eventValue2', $this->object->getParam('eventKey2')); $this->assertEquals(null, $this->object->getParam('eventKey3')); - global $register; - $pools = $register->get('pools'); - $client = new Client($this->object->getQueue(), $pools->get('queue')->pop()->getResource()); - $this->assertEquals($client->getQueueSize(), 1); + $this->assertCount(1, $this->publisher->getEvents($this->object->getQueue())); } public function testReset(): void diff --git a/tests/unit/Event/MockPublisher.php b/tests/unit/Event/MockPublisher.php new file mode 100644 index 0000000000..54fcc89358 --- /dev/null +++ b/tests/unit/Event/MockPublisher.php @@ -0,0 +1,35 @@ +events[$queue->name])) { + $this->events[$queue->name] = []; + } + $this->events[$queue->name][] = $payload; + return true; + } + + public function getEvents(string $queue) + { + return $this->events[$queue] ?? null; + } + + public function retry(Queue $queue, int $limit = null): void + { + // TODO: Implement retry() method. + } + + public function getQueueSize(Queue $queue, bool $failedJobs = false): int + { + return count($this->events[$queue->name]); + } +} diff --git a/tests/unit/Network/Validators/CNAMETest.php b/tests/unit/Network/Validators/CNAMETest.php deleted file mode 100644 index cbb07f19b5..0000000000 --- a/tests/unit/Network/Validators/CNAMETest.php +++ /dev/null @@ -1,29 +0,0 @@ -object = new CNAME('appwrite.io'); - } - - public function tearDown(): void - { - } - - public function testValues(): void - { - $this->assertEquals($this->object->isValid(''), false); - $this->assertEquals($this->object->isValid(null), false); - $this->assertEquals($this->object->isValid(false), false); - $this->assertEquals($this->object->isValid('cname-unit-test.appwrite.org'), true); - $this->assertEquals($this->object->isValid('test1.appwrite.org'), false); - } -} diff --git a/tests/unit/Network/Validators/DNSTest.php b/tests/unit/Network/Validators/DNSTest.php new file mode 100644 index 0000000000..5e8652381a --- /dev/null +++ b/tests/unit/Network/Validators/DNSTest.php @@ -0,0 +1,50 @@ +assertEquals($validator->isValid(''), false); + $this->assertEquals($validator->isValid(null), false); + $this->assertEquals($validator->isValid(false), false); + $this->assertEquals($validator->isValid('cname-unit-test.appwrite.org'), true); + $this->assertEquals($validator->isValid('test1.appwrite.org'), false); + } + + public function testA(): void + { + // IPv4 for documentation purposes + $validator = new DNS('203.0.113.1', DNS::RECORD_A); + $this->assertEquals($validator->isValid(''), false); + $this->assertEquals($validator->isValid(null), false); + $this->assertEquals($validator->isValid(false), false); + $this->assertEquals($validator->isValid('a-unit-test.appwrite.org'), true); + $this->assertEquals($validator->isValid('test1.appwrite.org'), false); + } + + public function testAAAA(): void + { + // IPv6 for documentation purposes + $validator = new DNS('2001:db8::1', DNS::RECORD_AAAA); + $this->assertEquals($validator->isValid(''), false); + $this->assertEquals($validator->isValid(null), false); + $this->assertEquals($validator->isValid(false), false); + $this->assertEquals($validator->isValid('aaaa-unit-test.appwrite.org'), true); + $this->assertEquals($validator->isValid('test1.appwrite.org'), false); + } +} diff --git a/tests/unit/Transformation/TransformationTest.php b/tests/unit/Transformation/TransformationTest.php new file mode 100644 index 0000000000..a3169026a3 --- /dev/null +++ b/tests/unit/Transformation/TransformationTest.php @@ -0,0 +1,43 @@ +addAdapter(new Mock()); + + $transformer->setInput($input); + $transformer->setTraits([]); + + $this->assertFalse($transformer->transform()); + + $transformer->setTraits(['mock' => true]); + $this->assertFalse($transformer->transform()); + + $transformer->setTraits(['mock' => true, 'content-type' => 'text/plain']); + $this->assertFalse($transformer->transform()); + + $transformer->setTraits(['mock' => true, 'content-type' => 'tExT/HtML']); + $this->assertFalse($transformer->transform()); + + $transformer->setTraits(['mock' => false, 'content-type' => 'text/plain, text/html; charset=utf-8']); + $this->assertFalse($transformer->transform()); + + $transformer->setTraits(['mock' => true, 'content-type' => 'text/plain, text/html; charset=utf-8']); + $this->assertTrue($transformer->transform()); + + $this->assertStringContainsString("Hello world", $transformer->getOutput()); + $this->assertStringContainsString("Preview by", $transformer->getOutput()); + $this->assertStringContainsString("Mock:", $transformer->getOutput()); + } +} diff --git a/tests/unit/Usage/StatsTest.php b/tests/unit/Usage/StatsTest.php deleted file mode 100644 index 79fa1f58ec..0000000000 --- a/tests/unit/Usage/StatsTest.php +++ /dev/null @@ -1,41 +0,0 @@ -get('pools')->get('queue')->pop()->getResource(); - $this->connection = $connection; - $this->client = new Client(self::QUEUE_NAME, $this->connection); - } - - public function tearDown(): void - { - } - - public function testSamePayload(): void - { - $inToQueue = [ - 'key_1' => 'value_1', - 'key_2' => 'value_2', - ]; - - $result = $this->client->enqueue($inToQueue); - $this->assertTrue($result); - $outFromQueue = $this->connection->leftPopArray('utopia-queue.queue.' . self::QUEUE_NAME, 0)['payload']; - $this->assertNotEmpty($outFromQueue); - $this->assertSame($inToQueue, $outFromQueue); - } -} diff --git a/tests/unit/Utopia/RequestTest.php b/tests/unit/Utopia/RequestTest.php index 73daaa88bc..e19fdbe01f 100644 --- a/tests/unit/Utopia/RequestTest.php +++ b/tests/unit/Utopia/RequestTest.php @@ -2,6 +2,7 @@ namespace Tests\Unit\Utopia; +use Appwrite\SDK\Method; use Appwrite\Utopia\Request; use PHPUnit\Framework\TestCase; use Swoole\Http\Request as SwooleRequest; @@ -31,8 +32,13 @@ class RequestTest extends TestCase $this->assertCount(2, $this->request->getFilters()); $route = new Route(Request::METHOD_GET, '/test'); - $route->label('sdk.method', 'method'); - $route->label('sdk.namespace', 'namespace'); + $route->label('sdk', new Method( + namespace: 'namespace', + name: 'method', + description: 'description', + auth: [], + responses: [], + )); // set test header to prevent header populaten inside the request class $this->request->addHeader('EXAMPLE', 'VALUE'); $this->request->setRoute($route);