diff --git a/.optimize-cache.json b/.optimize-cache.json index e52ed7770aa..a65e8845d13 100644 --- a/.optimize-cache.json +++ b/.optimize-cache.json @@ -1558,6 +1558,26 @@ "static/images/docs/platform/dark/execution-details.png": "c0481ddc206447460f9d317ba8d421615066f67a50bc9ef41a8f71766ecffb14", "static/images/docs/platform/env-variables.png": "16f95151e4f6ee9fb8056f075b9f5027fd91f0c2a28586c5624c3ffe9b7a1ee8", "static/images/docs/platform/execution-details.png": "ece1364b8b00254bbd982421b6eed6d7f519d34c4e80377fcaaa4cb5d5dd3f89", + "static/images/docs/project/auth-methods.png": "caa81b517332b06cf539edf25de91a444d8e19ac212d2dd8d75ba14f74933db6", + "static/images/docs/project/dark/auth-methods.png": "45421e0c586c5f7dc156e823642ab9667f97950f23ca01ce3b8d993ee49fb820", + "static/images/docs/project/dark/email-templates.png": "8bff7fd71fef2c2a30106ab93dab9daf26ff4ae4b3f1031fb502f2b5cede4a0f", + "static/images/docs/project/dark/labels.png": "b7c5abaa89675ab00356e468bafe159fe690881d9cb01d5eb1fb25c70ffa2d07", + "static/images/docs/project/dark/mock-phones.png": "f26a9cd69f3bc57279cd17109336ea8f55c40f22118b29bd3066afb678ebdf84", + "static/images/docs/project/dark/oauth-providers.png": "4d16fdb37b8f1de8c27a923aa0309e5dfd2bf7666621a11091d6443bed861bc4", + "static/images/docs/project/dark/platforms.png": "d8e1f107a3c9597ac703fa3c98279bf7bb398761c137455344a8cab05857ec0b", + "static/images/docs/project/dark/policies.png": "d51a421b4c57b4f2a0d28653e156325b113816a2ad096a2ff15bb15702362b6d", + "static/images/docs/project/dark/protocols.png": "ff39e7d76dd82d5d13024dd39f589f49ab159c67d1805cb32d3f8ba907b62822", + "static/images/docs/project/dark/services.png": "fd58dd37313629739db739392a287c5bd15cc196ebb9ed0095b069684aaf6218", + "static/images/docs/project/dark/smtp.png": "8ce568291e90b4e46039d9b8e19cc7ba4a57ccbbd452af8138ad68cc313b874d", + "static/images/docs/project/email-templates.png": "2e1c76df90f6337c13c95224254511b6cb27aa1e9d3568ca92d532fa00dfacb2", + "static/images/docs/project/labels.png": "c3c1da1332ce324bc9cc7506979eb62ae10864fc64fa133d011470748a155cea", + "static/images/docs/project/mock-phones.png": "ad8c936aafa4782f44611e1c8be9a0a85578485cff3ab49356355f10c178be4a", + "static/images/docs/project/oauth-providers.png": "14a9497cbfb216bc66ce0ce4709b598de640608c07976dda3261f63186df06bc", + "static/images/docs/project/platforms.png": "7200e9aee04f6fcbc1d232a474b9f80ed406e78ec981c59f69f576649fa8f564", + "static/images/docs/project/policies.png": "1a35fa9333be000e5131e011fa7e7644aea1148e43d238fa51c98366b7d5871b", + "static/images/docs/project/protocols.png": "22bfbe1bc2960244c467d8dc373d4b021a79ee9a9b01e9e1d89c5cf3b0bea385", + "static/images/docs/project/services.png": "b7bb5785e64fdace11e6989a070e326cd1dfc5a67de9a8e17e80ebde20c5fbdf", + "static/images/docs/project/smtp.png": "52a456cd65a8aa9049bbd09168d945b10ece6f80ddf6c15f4ab2fc40affa9fc7", "static/images/docs/quick-starts/add-platform.png": "3b13ba983ea1d2529a1f34a719acef903ec0b58879ed511012280a28ccbde17e", "static/images/docs/quick-starts/create-project.png": "7fdb25def02c5dbdb08cd38c2d03b7b454c930194a900553e3e68d51cb28a1d5", "static/images/docs/quick-starts/dark/add-platform.png": "b12a85b64b136589268831b9cb26a664ec97418ad25a38be5273baab8253aa16", diff --git a/src/redirects.json b/src/redirects.json index 17340a23b84..1bd79068822 100644 --- a/src/redirects.json +++ b/src/redirects.json @@ -1,4 +1,12 @@ [ + { + "link": "/docs/advanced/platform/api-keys", + "redirect": "/docs/platforms/project/api-keys" + }, + { + "link": "/docs/advanced/platform/environment-variables", + "redirect": "/docs/platforms/project/environment-variables" + }, { "link": "/docs/getting-started-for-web", "redirect": "/docs/quick-starts" @@ -201,7 +209,7 @@ }, { "link": "/docs/keys", - "redirect": "/docs/advanced/platform/api-keys" + "redirect": "/docs/platforms/project/api-keys" }, { "link": "/docs/permissions", diff --git a/src/routes/blog/post/announcing-projects-api/+page.markdoc b/src/routes/blog/post/announcing-projects-api/+page.markdoc new file mode 100644 index 00000000000..ca4250fe454 --- /dev/null +++ b/src/routes/blog/post/announcing-projects-api/+page.markdoc @@ -0,0 +1,552 @@ +--- +layout: post +title: "Announcing the Projects API: Configure your project with Server SDKs" +description: Every project setting, from auth methods and OAuth providers to SMTP and labels, can now be configured programmatically through the Appwrite Server SDKs. +date: 2026-06-05 +cover: /images/blog/announcing-projects-api/cover.avif +timeToRead: 5 +author: matej-baco +category: announcement +featured: false +callToAction: true +faqs: + - question: "What is the Appwrite Projects API?" + answer: "It is a set of endpoints on the `Project` service that let you configure and read a project's settings programmatically from any Appwrite Server SDK. Previously, settings like auth methods, OAuth providers, and SMTP could only be changed through the Appwrite Console." + - question: "What can I configure with the Projects API?" + answer: "Auth methods, OAuth2 providers, API keys, platforms, protocols, services, password and session policies, environment variables, custom SMTP, email templates, mock phone numbers, and project labels. You can also read the full project configuration with `project.get`." + - question: "What does the Projects API require?" + answer: "An API key with the relevant scopes. Reading the project uses `project.read`, most configuration uses `project.write`, and some resources have dedicated scopes such as `platforms.write`, `templates.write`, or `keys.write`. These keys are server-side credentials, so keep them out of client applications." + - question: "How is the Projects API different from the Console?" + answer: "It exposes the same project settings as the Console through code. Anything you configure by clicking through the Console you can now script, version, and review, which makes project setup repeatable across environments." + - question: "Which SDKs support the Projects API?" + answer: "All Appwrite Server SDKs, including Node.js, Python, PHP, Ruby, .NET, Dart, Kotlin, Java, Swift, Go, and Rust, along with the Appwrite CLI. Per-language examples are in the [Projects API documentation](/docs/platforms/project)." + - question: "Can I create a project with the Projects API?" + answer: "The Projects API manages the settings of an existing project and reads it with `project.get`. Creating a project still happens in the Appwrite Console." +--- + +Configuring a project has always meant working through the Appwrite Console: toggling auth methods, pasting OAuth credentials, registering platforms, and setting up SMTP one screen at a time. For a single project, that is fine. For teams managing several environments, onboarding new projects, or rebuilding a configuration from scratch, repeating those steps by hand becomes a bottleneck. + +Today, we are announcing the **Projects API**, which lets you configure and read every project setting programmatically through the Appwrite Server SDKs. + +This is part of a wider effort to make everything in Appwrite accessible through the API. Our goal is to ensure that any action you can perform in the Appwrite Console can also be done programmatically, giving you full control over your projects through code. + +# Why this matters + +A project's configuration is the foundation every other resource sits on. Which auth methods are enabled, which platforms can connect, how email is delivered: these decisions shape how your app behaves. Managing them from code opens up workflows that were previously manual: + +- **Reproducible environments** where development, staging, and production projects are configured from the same script +- **Project provisioning** that sets up auth, platforms, and policies for a new project in one run +- **Multi-tenant platforms** that configure a project per customer without Console access +- **Configuration in version control**, so changes to a project are reviewed and tracked like any other code + +# What you can configure + +The Projects API covers the full surface of project settings, grouped into a few areas: + +- **Authentication**: enable or disable [auth methods](/docs/platforms/project/auth-methods), configure [OAuth2 providers](/docs/platforms/project/oauth), and set [password and session policies](/docs/platforms/project/policies). +- **Access**: create and manage [API keys](/docs/platforms/project/api-keys), register [platforms](/docs/platforms/project/platforms), and toggle [protocols](/docs/platforms/project/protocols) and [services](/docs/platforms/project/services). +- **Email**: configure a custom [SMTP server](/docs/platforms/project/smtp), customize [email templates](/docs/platforms/project/email-templates), and send test emails. +- **Project**: manage [environment variables](/docs/platforms/project/environment-variables), register [mock phone numbers](/docs/platforms/project/mock-phones) for testing, assign [labels](/docs/platforms/project/labels), and read the full configuration with `project.get`. + +# How it works + +Every operation lives on the `Project` service. Initialize a Server SDK with an API key, then call the settings you need. For example, registering a web platform that is allowed to call your project: + +{% multicode %} +```server-nodejs +import { Client, Project, ID } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.createWebPlatform({ + platformId: ID.unique(), + name: 'My Web App', + hostname: 'app.example.com' +}); +``` +```server-deno +import { Client, Project, ID } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.createWebPlatform({ + platformId: ID.unique(), + name: 'My Web App', + hostname: 'app.example.com' +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->createWebPlatform( + platformId: ID::unique(), + name: 'My Web App', + hostname: 'app.example.com' +); +``` +```server-python +from appwrite.client import Client +from appwrite.id import ID +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.create_web_platform( + platform_id = ID.unique(), + name = 'My Web App', + hostname = 'app.example.com' +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.create_web_platform( + platform_id: ID.unique(), + name: 'My Web App', + hostname: 'app.example.com' +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.CreateWebPlatform( + platformId: ID.Unique(), + name: "My Web App", + hostname: "app.example.com" +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.createWebPlatform( + platformId: ID.unique(), + name: 'My Web App', + hostname: 'app.example.com', +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.ID +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.createWebPlatform( + platformId = ID.unique(), + name = "My Web App", + hostname = "app.example.com" +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.ID; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.createWebPlatform( + ID.unique(), // platformId + "My Web App", // name + "app.example.com", // hostname + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.createWebPlatform( + platformId: ID.unique(), + name: "My Web App", + hostname: "app.example.com" +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" + "github.com/appwrite/sdk-for-go/id" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.CreateWebPlatform( + id.Unique(), + "My Web App", + "app.example.com", + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::id::ID; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new(); + client.set_endpoint("https://.cloud.appwrite.io/v1"); + client.set_project(""); + client.set_key(""); + + let project = Project::new(&client); + + let result = project.create_web_platform( + ID::unique(), + "My Web App", + "app.example.com", + ).await?; + + let _ = result; + + Ok(()) +} +``` +{% /multicode %} + +Or controlling which API protocols clients can use to reach your project, for example enabling REST: + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectProtocolId } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateProtocol({ + protocolId: ProjectProtocolId.Rest, + enabled: true +}); +``` +```server-deno +import { Client, Project, ProjectProtocolId } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateProtocol({ + protocolId: ProjectProtocolId.Rest, + enabled: true +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateProtocol( + protocolId: ProjectProtocolId::REST(), + enabled: true +); +``` +```server-python +from appwrite.client import Client +from appwrite.enums import ProjectProtocolId +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_protocol( + protocol_id = ProjectProtocolId.REST, + enabled = True +) +``` +```server-ruby +require 'appwrite' + +include Appwrite +include Appwrite::Enums + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_protocol( + protocol_id: ProjectProtocolId::REST, + enabled: true +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateProtocol( + protocolId: ProjectProtocolId.Rest, + enabled: true +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateProtocol( + protocolId: enums.ProjectProtocolId.rest, + enabled: true, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.enums.ProjectProtocolId +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateProtocol( + protocolId = ProjectProtocolId.REST, + enabled = true +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.enums.ProjectProtocolId; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateProtocol( + ProjectProtocolId.REST, // protocolId + true, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateProtocol( + protocolId: .rest, + enabled: true +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.UpdateProtocol( + "rest", + true, + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; +use appwrite::enums::ProjectProtocolId; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new(); + client.set_endpoint("https://.cloud.appwrite.io/v1"); + client.set_project(""); + client.set_key(""); + + let project = Project::new(&client); + + let result = project.update_protocol( + ProjectProtocolId::Rest, + true + ).await?; + + let _ = result; + + Ok(()) +} +``` +{% /multicode %} + +Every setting maps to a method on the `Project` service, available across all Server SDKs with the matching object or named parameters. + +# Full SDK support + +The Projects API is available across all Appwrite Server SDKs, including Node.js, Python, PHP, Ruby, .NET, Dart, Kotlin, Java, Swift, Go, and Rust, as well as the Appwrite CLI. Complete code examples for every operation and language are in the [Projects API documentation](/docs/platforms/project). + +# Get started + +The Projects API is available on **Appwrite Cloud** today. + +1. Create an [API key](/docs/platforms/project/api-keys) with the scopes for the settings you want to manage. +2. Initialize a Server SDK with your API key. +3. Use the `Project` service to configure your project from code. + +# Resources + +- [Projects API documentation](/docs/platforms/project) +- [Auth methods](/docs/platforms/project/auth-methods) +- [OAuth providers](/docs/platforms/project/oauth) +- [API keys](/docs/platforms/project/api-keys) +- [Platforms](/docs/platforms/project/platforms) +- [SMTP](/docs/platforms/project/smtp) +- [Email templates](/docs/platforms/project/email-templates) diff --git a/src/routes/docs/Sidebar.svelte b/src/routes/docs/Sidebar.svelte index c03804aa501..fc03b3dab64 100644 --- a/src/routes/docs/Sidebar.svelte +++ b/src/routes/docs/Sidebar.svelte @@ -93,6 +93,17 @@ } ] }, + { + label: 'Platforms', + items: [ + { + label: 'Project', + href: '/docs/platforms/project', + icon: 'icon-briefcase', + isParent: true + } + ] + }, { label: 'Utilities', collapsible: true, diff --git a/src/routes/docs/advanced/platform/+layout.svelte b/src/routes/docs/advanced/platform/+layout.svelte index 219c63c770e..00fdefe579c 100644 --- a/src/routes/docs/advanced/platform/+layout.svelte +++ b/src/routes/docs/advanced/platform/+layout.svelte @@ -59,10 +59,6 @@ label: 'Rate limits', href: '/docs/advanced/platform/rate-limits' }, - { - label: 'API keys', - href: '/docs/advanced/platform/api-keys' - }, { label: 'Dev keys', href: '/docs/advanced/platform/dev-keys' @@ -126,11 +122,6 @@ label: 'Custom domains', href: '/docs/advanced/platform/custom-domains' }, - { - label: 'Environment variables', - new: isNewUntil('30 May 2026'), - href: '/docs/advanced/platform/environment-variables' - }, { label: 'Message templates', href: '/docs/advanced/platform/message-templates' diff --git a/src/routes/docs/advanced/platform/+page.markdoc b/src/routes/docs/advanced/platform/+page.markdoc index d85400548e1..d87454b7ec5 100644 --- a/src/routes/docs/advanced/platform/+page.markdoc +++ b/src/routes/docs/advanced/platform/+page.markdoc @@ -46,10 +46,6 @@ Control which users can access which resources. Appwrite has rate limits on some endpoints to prevent abuse. {% /cards_item %} -{% cards_item href="/docs/advanced/platform/api-keys" title="API keys" %} -Create and manage API keys used by Server SDKs. -{% /cards_item %} - {% cards_item href="/docs/advanced/platform/dev-keys" title="Dev keys" %} Create and manage dev keys used by Client SDKs in dev environments. {% /cards_item %} diff --git a/src/routes/docs/platforms/project/+layout.svelte b/src/routes/docs/platforms/project/+layout.svelte new file mode 100644 index 00000000000..42372e3586b --- /dev/null +++ b/src/routes/docs/platforms/project/+layout.svelte @@ -0,0 +1,79 @@ + + + + + + diff --git a/src/routes/docs/platforms/project/+page.markdoc b/src/routes/docs/platforms/project/+page.markdoc new file mode 100644 index 00000000000..64a82ec2fab --- /dev/null +++ b/src/routes/docs/platforms/project/+page.markdoc @@ -0,0 +1,443 @@ +--- +layout: article +title: Project +description: Configure your Appwrite project, including auth methods, platforms, protocols, services, and policies. +back: /docs +--- + +An Appwrite **Project** is the top-level container for all the resources your app uses, from users and databases to storage buckets and functions. The settings on a project control which authentication methods are available, which client platforms can connect, which protocols and services are exposed, and which policies apply to the resources inside it. + +# Concepts {% #concepts %} + +{% cards %} +{% cards_item href="/docs/platforms/project/auth-methods" title="Auth methods" %} +Enable or disable authentication methods on your project. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/oauth" title="OAuth providers" %} +Configure OAuth2 sign-in providers like Google, GitHub, and Apple. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/api-keys" title="API keys" %} +Create and manage API keys used by Server SDKs. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/platforms" title="Platforms" %} +Register the apps and origins that are allowed to call your project. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/protocols" title="Protocols" %} +Toggle the API protocols clients can use to reach your project. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/services" title="Services" %} +Turn individual Appwrite services on or off for your project. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/policies" title="Policies" %} +Configure project-wide policies that apply across resources. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/mock-phones" title="Mock phones" %} +Register fictional phone numbers and OTPs to test phone authentication. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/environment-variables" title="Environment variables" %} +Share constants and secrets across your functions and sites. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/smtp" title="SMTP" %} +Send emails from your own custom SMTP server. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/email-templates" title="Email templates" %} +Customize the account management emails Appwrite sends to your users. +{% /cards_item %} +{% cards_item href="/docs/platforms/project/labels" title="Labels" %} +Tag projects with customizable labels to organize and filter them. +{% /cards_item %} +{% /cards %} + +# Retrieve your project {% #get-project %} + +Fetch your project's current configuration in a single call, including its name, region, labels, and the settings managed on the pages above. Use a [Server SDK](/docs/sdks#server). + +{% info title="Required scope" %} +The API key used for this call needs the `project.read` scope. +{% /info %} + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.get(); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.get(); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your API key + +$project = new Project($client); + +$result = $project->get(); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import Project as ProjectModel + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your API key + +project = Project(client) + +result: ProjectModel = project.get() + +print(result.model_dump()) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your API key + +project = Project.new(client) + +result = project.get +``` +```server-dotnet +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 + .SetKey(""); // Your API key + +Project project = new Project(client); + +Project result = await project.Get(); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +Project project = Project(client); + +Project result = await project.get(); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +val project = Project(client) + +val response = project.get() +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your API key + +Project project = new Project(client); + +project.get(new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); +})); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +let project = Project(client) + +let result = try await project.get() +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.Get() + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new(); + client.set_endpoint("https://.cloud.appwrite.io/v1"); // Your API Endpoint + client.set_project(""); // Your project ID + client.set_key(""); // Your API key + + let project = Project::new(&client); + + let result = project.get().await?; + + let _ = result; + + Ok(()) +} +``` +{% /multicode %} + +# Delete a project {% #delete-project %} + +{% info title="Permanent and irreversible" %} +Deleting a project permanently removes it along with every resource inside it, including users, databases, storage, functions, and sites. This action cannot be undone. The call targets the project tied to the API key and endpoint you initialize the SDK with, so make sure you are pointing at the project you intend to delete. +{% /info %} + +The `delete` method requires an API key with the `project.write` scope. It takes no parameters and acts on the project the request is scoped to. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.delete(); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.delete(); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your API key + +$project = new Project($client); + +$result = $project->delete(); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your API key + +project = Project(client) + +result = project.delete() +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your API key + +project = Project.new(client) + +result = project.delete() +``` +```server-dotnet +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 + .SetKey(""); // Your API key + +Project project = new Project(client); + +await project.Delete(); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +Project project = Project(client); + +await project.delete(); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +val project = Project(client) + +val response = project.delete() +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your API key + +Project project = new Project(client); + +project.delete(new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); +})); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +let project = Project(client) + +let result = try await project.delete() +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.Delete() + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new(); + client.set_endpoint("https://.cloud.appwrite.io/v1"); // Your API Endpoint + client.set_project(""); // Your project ID + client.set_key(""); // Your API key + + let project = Project::new(&client); + + project.delete().await?; + + Ok(()) +} +``` +```bash +appwrite project delete +``` +{% /multicode %} diff --git a/src/routes/docs/advanced/platform/api-keys/+page.markdoc b/src/routes/docs/platforms/project/api-keys/+page.markdoc similarity index 81% rename from src/routes/docs/advanced/platform/api-keys/+page.markdoc rename to src/routes/docs/platforms/project/api-keys/+page.markdoc index 544159552ef..aa0cbe5b2e3 100644 --- a/src/routes/docs/advanced/platform/api-keys/+page.markdoc +++ b/src/routes/docs/platforms/project/api-keys/+page.markdoc @@ -23,10 +23,10 @@ API keys are for server SDKs and the CLI in production environments, while Dev k # Create API key {% #create-api-key %} {% only_dark %} -![Project settings screen](/images/docs/platform/dark/create-api-key.avif) +![Project settings screen](/images/docs/project/dark/create-api-key.avif) {% /only_dark %} {% only_light %} -![Project settings screen](/images/docs/platform/create-api-key.avif) +![Project settings screen](/images/docs/project/create-api-key.avif) {% /only_light %} To create a new API key, navigate to **Overview** > **Integration** > **API keys** and click **Create API key**. @@ -567,7 +567,7 @@ async fn main() -> Result<(), Box> { {% multicode %} ```server-nodejs -import { Client, Project, ID, Scopes } from 'node-appwrite'; +import { Client, Project, ID, ProjectKeyScopes } from 'node-appwrite'; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') @@ -579,12 +579,12 @@ const project = new Project(client); const result = await project.createKey({ keyId: ID.unique(), name: 'My API Key', - scopes: [Scopes.DatabasesRead, Scopes.DatabasesWrite], + scopes: [ProjectKeyScopes.DatabasesRead, ProjectKeyScopes.DatabasesWrite], expire: '2026-12-31T23:59:59.000+00:00' }); ``` ```server-deno -import { Client, Project, ID, Scopes } from "npm:node-appwrite"; +import { Client, Project, ID, ProjectKeyScopes } from "npm:node-appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') @@ -596,7 +596,7 @@ const project = new Project(client); const result = await project.createKey({ keyId: ID.unique(), name: 'My API Key', - scopes: [Scopes.DatabasesRead, Scopes.DatabasesWrite], + scopes: [ProjectKeyScopes.DatabasesRead, ProjectKeyScopes.DatabasesWrite], expire: '2026-12-31T23:59:59.000+00:00' }); ``` @@ -627,7 +627,7 @@ $result = $project->createKey( from appwrite.client import Client from appwrite.id import ID from appwrite.services.project import Project -from appwrite.enums.scopes import Scopes +from appwrite.enums import ProjectKeyScopes client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') @@ -639,7 +639,7 @@ project = Project(client) result = project.create_key( key_id=ID.unique(), name='My API Key', - scopes=[Scopes.DATABASES_READ, Scopes.DATABASES_WRITE], + scopes=[ProjectKeyScopes.DATABASES_READ, ProjectKeyScopes.DATABASES_WRITE], expire='2026-12-31T23:59:59.000+00:00' ) ``` @@ -678,7 +678,7 @@ Project project = new Project(client); var result = await project.CreateKey( keyId: ID.Unique(), name: "My API Key", - scopes: new List {Scopes.DatabasesRead, Scopes.DatabasesWrite}, + scopes: new List {ProjectKeyScopes.DatabasesRead, ProjectKeyScopes.DatabasesWrite}, expire: "2026-12-31T23:59:59.000+00:00" ); ``` @@ -696,14 +696,14 @@ Project project = Project(client); final result = await project.createKey( keyId: ID.unique(), name: 'My API Key', - scopes: [enums.Scopes.databasesRead, enums.Scopes.databasesWrite], + scopes: [enums.ProjectKeyScopes.databasesRead, enums.ProjectKeyScopes.databasesWrite], expire: '2026-12-31T23:59:59.000+00:00', ); ``` ```server-kotlin import io.appwrite.Client import io.appwrite.ID -import io.appwrite.enums.Scopes +import io.appwrite.enums.ProjectKeyScopes import io.appwrite.services.Project val client = Client() @@ -716,14 +716,14 @@ val project = Project(client) val result = project.createKey( keyId = ID.unique(), name = "My API Key", - scopes = listOf(Scopes.DATABASES_READ, Scopes.DATABASES_WRITE), + scopes = listOf(ProjectKeyScopes.DATABASES_READ, ProjectKeyScopes.DATABASES_WRITE), expire = "2026-12-31T23:59:59.000+00:00" ) ``` ```server-java import io.appwrite.Client; import io.appwrite.ID; -import io.appwrite.enums.Scopes; +import io.appwrite.enums.ProjectKeyScopes; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Project; @@ -737,7 +737,7 @@ Project project = new Project(client); project.createKey( ID.unique(), // keyId "My API Key", // name - List.of(Scopes.DATABASES_READ, Scopes.DATABASES_WRITE), // scopes + List.of(ProjectKeyScopes.DATABASES_READ, ProjectKeyScopes.DATABASES_WRITE), // scopes "2026-12-31T23:59:59.000+00:00", // expire new CoroutineCallback<>((result, error) -> { if (error != null) { @@ -762,7 +762,7 @@ let project = Project(client) let result = try await project.createKey( keyId: ID.unique(), name: "My API Key", - scopes: [Scopes.databasesRead, Scopes.databasesWrite], + scopes: [ProjectKeyScopes.databasesRead, ProjectKeyScopes.databasesWrite], expire: "2026-12-31T23:59:59.000+00:00" ) ``` @@ -800,7 +800,7 @@ func main() { ```server-rust use appwrite::Client; use appwrite::id::ID; -use appwrite::enums::Scopes; +use appwrite::enums::ProjectKeyScopes; use appwrite::services::project::Project; #[tokio::main] @@ -815,7 +815,7 @@ async fn main() -> Result<(), Box> { let result = project.create_key( ID::unique(), // key_id "My API Key", // name - vec![Scopes::DatabasesRead, Scopes::DatabasesWrite], // scopes + vec![ProjectKeyScopes::DatabasesRead, ProjectKeyScopes::DatabasesWrite], // scopes Some("2026-12-31T23:59:59.000+00:00"), // expire ).await?; @@ -825,11 +825,244 @@ async fn main() -> Result<(), Box> { ``` {% /multicode %} +## Create an ephemeral key {% #create-an-ephemeral-key %} + +Ephemeral keys are short-lived API keys that expire after a set duration, useful for temporary or single-session server access without managing a long-lived key. Pass the `scopes` to grant and a `duration` in seconds (maximum 3600). The response includes the generated secret and its expiration time. + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectKeyScopes } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.createEphemeralKey({ + scopes: [ProjectKeyScopes.TablesRead, ProjectKeyScopes.TablesWrite], + duration: 600 +}); +``` +```server-deno +import { Client, Project, ProjectKeyScopes } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.createEphemeralKey({ + scopes: [ProjectKeyScopes.TablesRead, ProjectKeyScopes.TablesWrite], + duration: 600 +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->createEphemeralKey( + scopes: ['tables.read', 'tables.write'], + duration: 600 +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.enums import ProjectKeyScopes + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.create_ephemeral_key( + scopes=[ProjectKeyScopes.TABLES_READ, ProjectKeyScopes.TABLES_WRITE], + duration=600 +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.create_ephemeral_key( + scopes: ['tables.read', 'tables.write'], + duration: 600 +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.CreateEphemeralKey( + scopes: new List {ProjectKeyScopes.TablesRead, ProjectKeyScopes.TablesWrite}, + duration: 600 +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.createEphemeralKey( + scopes: [enums.ProjectKeyScopes.tablesRead, enums.ProjectKeyScopes.tablesWrite], + duration: 600, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.enums.ProjectKeyScopes +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val result = project.createEphemeralKey( + scopes = listOf(ProjectKeyScopes.TABLES_READ, ProjectKeyScopes.TABLES_WRITE), + duration = 600 +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.enums.ProjectKeyScopes; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.createEphemeralKey( + List.of(ProjectKeyScopes.TABLES_READ, ProjectKeyScopes.TABLES_WRITE), // scopes + 600, // duration + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.createEphemeralKey( + scopes: [ProjectKeyScopes.tablesRead, ProjectKeyScopes.tablesWrite], + duration: 600 +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.CreateEphemeralKey( + []string{"tables.read", "tables.write"}, + 600, + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::enums::ProjectKeyScopes; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.create_ephemeral_key( + vec![ProjectKeyScopes::TablesRead, ProjectKeyScopes::TablesWrite], // scopes + 600, // duration + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +{% /multicode %} + ## Update an API key {% #update-an-api-key %} {% multicode %} ```server-nodejs -import { Client, Project, Scopes } from 'node-appwrite'; +import { Client, Project, ProjectKeyScopes } from 'node-appwrite'; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') @@ -841,12 +1074,12 @@ const project = new Project(client); const result = await project.updateKey({ keyId: '', name: 'Updated Key', - scopes: [Scopes.DatabasesRead, Scopes.DatabasesWrite, Scopes.UsersRead], + scopes: [ProjectKeyScopes.DatabasesRead, ProjectKeyScopes.DatabasesWrite, ProjectKeyScopes.UsersRead], expire: '2027-06-30T23:59:59.000+00:00' }); ``` ```server-deno -import { Client, Project, Scopes } from "npm:node-appwrite"; +import { Client, Project, ProjectKeyScopes } from "npm:node-appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') @@ -858,7 +1091,7 @@ const project = new Project(client); const result = await project.updateKey({ keyId: '', name: 'Updated Key', - scopes: [Scopes.DatabasesRead, Scopes.DatabasesWrite, Scopes.UsersRead], + scopes: [ProjectKeyScopes.DatabasesRead, ProjectKeyScopes.DatabasesWrite, ProjectKeyScopes.UsersRead], expire: '2027-06-30T23:59:59.000+00:00' }); ``` @@ -887,7 +1120,7 @@ $result = $project->updateKey( ```server-python from appwrite.client import Client from appwrite.services.project import Project -from appwrite.enums.scopes import Scopes +from appwrite.enums import ProjectKeyScopes client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') @@ -899,7 +1132,7 @@ project = Project(client) result = project.update_key( key_id='', name='Updated Key', - scopes=[Scopes.DATABASES_READ, Scopes.DATABASES_WRITE, Scopes.USERS_READ], + scopes=[ProjectKeyScopes.DATABASES_READ, ProjectKeyScopes.DATABASES_WRITE, ProjectKeyScopes.USERS_READ], expire='2027-06-30T23:59:59.000+00:00' ) ``` @@ -938,7 +1171,7 @@ Project project = new Project(client); var result = await project.UpdateKey( keyId: "", name: "Updated Key", - scopes: new List {Scopes.DatabasesRead, Scopes.DatabasesWrite, Scopes.UsersRead}, + scopes: new List {ProjectKeyScopes.DatabasesRead, ProjectKeyScopes.DatabasesWrite, ProjectKeyScopes.UsersRead}, expire: "2027-06-30T23:59:59.000+00:00" ); ``` @@ -956,13 +1189,13 @@ Project project = Project(client); final result = await project.updateKey( keyId: '', name: 'Updated Key', - scopes: [enums.Scopes.databasesRead, enums.Scopes.databasesWrite, enums.Scopes.usersRead], + scopes: [enums.ProjectKeyScopes.databasesRead, enums.ProjectKeyScopes.databasesWrite, enums.ProjectKeyScopes.usersRead], expire: '2027-06-30T23:59:59.000+00:00', ); ``` ```server-kotlin import io.appwrite.Client -import io.appwrite.enums.Scopes +import io.appwrite.enums.ProjectKeyScopes import io.appwrite.services.Project val client = Client() @@ -975,13 +1208,13 @@ val project = Project(client) val result = project.updateKey( keyId = "", name = "Updated Key", - scopes = listOf(Scopes.DATABASES_READ, Scopes.DATABASES_WRITE, Scopes.USERS_READ), + scopes = listOf(ProjectKeyScopes.DATABASES_READ, ProjectKeyScopes.DATABASES_WRITE, ProjectKeyScopes.USERS_READ), expire = "2027-06-30T23:59:59.000+00:00" ) ``` ```server-java import io.appwrite.Client; -import io.appwrite.enums.Scopes; +import io.appwrite.enums.ProjectKeyScopes; import io.appwrite.coroutines.CoroutineCallback; import io.appwrite.services.Project; @@ -995,7 +1228,7 @@ Project project = new Project(client); project.updateKey( "", // keyId "Updated Key", // name - List.of(Scopes.DATABASES_READ, Scopes.DATABASES_WRITE, Scopes.USERS_READ), // scopes + List.of(ProjectKeyScopes.DATABASES_READ, ProjectKeyScopes.DATABASES_WRITE, ProjectKeyScopes.USERS_READ), // scopes "2027-06-30T23:59:59.000+00:00", // expire new CoroutineCallback<>((result, error) -> { if (error != null) { @@ -1020,7 +1253,7 @@ let project = Project(client) let result = try await project.updateKey( keyId: "", name: "Updated Key", - scopes: [Scopes.databasesRead, Scopes.databasesWrite, Scopes.usersRead], + scopes: [ProjectKeyScopes.databasesRead, ProjectKeyScopes.databasesWrite, ProjectKeyScopes.usersRead], expire: "2027-06-30T23:59:59.000+00:00" ) ``` @@ -1056,7 +1289,7 @@ func main() { ``` ```server-rust use appwrite::Client; -use appwrite::enums::Scopes; +use appwrite::enums::ProjectKeyScopes; use appwrite::services::project::Project; #[tokio::main] @@ -1071,7 +1304,7 @@ async fn main() -> Result<(), Box> { let result = project.update_key( "", // key_id "Updated Key", // name - vec![Scopes::DatabasesRead, Scopes::DatabasesWrite, Scopes::UsersRead], // scopes + vec![ProjectKeyScopes::DatabasesRead, ProjectKeyScopes::DatabasesWrite, ProjectKeyScopes::UsersRead], // scopes Some("2027-06-30T23:59:59.000+00:00"), // expire ).await?; diff --git a/src/routes/docs/platforms/project/auth-methods/+page.markdoc b/src/routes/docs/platforms/project/auth-methods/+page.markdoc new file mode 100644 index 00000000000..7f833e22bca --- /dev/null +++ b/src/routes/docs/platforms/project/auth-methods/+page.markdoc @@ -0,0 +1,287 @@ +--- +layout: article +title: Auth methods +description: Enable or disable authentication methods on your Appwrite project programmatically using server SDKs. +--- + +Each Appwrite project ships with a configurable set of authentication methods, including email and password, magic URL, email OTP, phone, anonymous sessions, JWT, and team invites. Methods can be toggled on or off from the Appwrite Console under **Auth** > **Settings**, or programmatically through any server SDK using the Project service. + +When a method is disabled, the matching account endpoints reject requests for that project until it is re-enabled. + +# Toggle from the Console {% #toggle-console %} + +{% only_dark %} +![Auth methods settings in the Appwrite Console](/images/docs/project/dark/auth-methods.avif) +{% /only_dark %} +{% only_light %} +![Auth methods settings in the Appwrite Console](/images/docs/project/auth-methods.avif) +{% /only_light %} + +To toggle auth methods manually: + +1. Open your project in the Appwrite Console. +2. Navigate to **Auth** in the sidebar, then open the **Settings** tab. +3. In the **Auth methods** card, toggle individual methods on or off, or use **Enable all** or **Disable all** for bulk changes. +4. Changes take effect immediately. No deploy or restart is required. + +OAuth2 providers are configured separately in the **OAuth2 Providers** section on the same page. + +# Method IDs {% #method-ids %} + +The `methodId` parameter accepts one of the following values: + +| Method ID | Description | +| --- | --- | +| `email-password` | Email and password sign-up and login. | +| `magic-url` | Passwordless login using a magic link sent to the user's email. | +| `email-otp` | Time-based one-time password sent to the user's email. | +| `phone` | SMS-based phone authentication. | +| `anonymous` | Guest sessions for unauthenticated visitors. | +| `invites` | Team invitations for collaborative access. | +| `jwt` | JWT-based authentication for delegated access. | + +# Enable or disable a method {% #update-auth-method %} + +Use the Project service `updateAuthMethod` endpoint with a method ID and the `enabled` flag. + +{% info title="Required scope" %} +The API key used for these calls needs the `project.write` scope. +{% /info %} + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectAuthMethodId } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateAuthMethod({ + methodId: ProjectAuthMethodId.Emailpassword, + enabled: false +}); +``` +```server-deno +import { Client, Project, ProjectAuthMethodId } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateAuthMethod({ + methodId: ProjectAuthMethodId.Emailpassword, + enabled: false +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateAuthMethod( + methodId: ProjectAuthMethodId::EMAILPASSWORD(), + enabled: false +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.enums import ProjectAuthMethodId + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_auth_method( + method_id = ProjectAuthMethodId.EMAIL_PASSWORD, + enabled = False +) +``` +```server-ruby +require 'appwrite' + +include Appwrite +include Appwrite::Enums + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_auth_method( + method_id: ProjectAuthMethodId::EMAIL_PASSWORD, + enabled: false +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateAuthMethod( + methodId: ProjectAuthMethodId.EmailPassword, + enabled: false +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateAuthMethod( + methodId: enums.ProjectAuthMethodId.emailPassword, + enabled: false, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project +import io.appwrite.enums.ProjectAuthMethodId + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val result = project.updateAuthMethod( + methodId = ProjectAuthMethodId.EMAIL_PASSWORD, + enabled = false +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; +import io.appwrite.enums.ProjectAuthMethodId; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateAuthMethod( + ProjectAuthMethodId.EMAIL_PASSWORD, // methodId + false, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateAuthMethod( + methodId: .emailPassword, + enabled: false +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.UpdateAuthMethod( + "email-password", + false, + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; +use appwrite::enums::ProjectAuthMethodId; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_auth_method( + ProjectAuthMethodId::EmailPassword, + false, + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-auth-method \ + --method-id email-password \ + --enabled false +``` +{% /multicode %} + +The endpoint returns the updated [Project](/docs/references/cloud/models/project) document with the new method state applied. diff --git a/src/routes/docs/platforms/project/email-templates/+page.markdoc b/src/routes/docs/platforms/project/email-templates/+page.markdoc new file mode 100644 index 00000000000..8b6689e3f60 --- /dev/null +++ b/src/routes/docs/platforms/project/email-templates/+page.markdoc @@ -0,0 +1,872 @@ +--- +layout: article +title: Email templates +description: Customize the account management emails Appwrite sends to your users, including verification, password recovery, and magic URL emails, per locale. +--- + +Appwrite sends transactional emails on your behalf for account management flows such as email verification, password recovery, and magic URL sign-in. Email templates let you customize the subject, message body, sender identity, and reply-to address of each of these emails, with a separate version for every locale you support. + +{% info title="Custom SMTP required to save changes" %} +You can view the built-in default templates at any time, but saving a customization requires a custom SMTP server enabled on your project. See [Custom SMTP server](/docs/advanced/platform/message-templates#smtp) to set one up. +{% /info %} + +# Manage in the Console {% #console %} + +{% only_dark %} +![Email templates in the Appwrite Console](/images/docs/project/dark/email-templates.avif) +{% /only_dark %} +{% only_light %} +![Email templates in the Appwrite Console](/images/docs/project/email-templates.avif) +{% /only_light %} + +To edit email templates from the Appwrite Console: + +1. Navigate to your project. +2. Open the **Auth** section and select the **Templates** tab. +3. Under **Email templates**, expand the template you want to edit, such as **Verification** or **Reset password**. +4. Choose a **Template language**, then edit the sender name, sender email, reply-to address, subject, and message. Use the variable chips (`{{user}}`, `{{project}}`, `{{redirect}}`) to insert dynamic values into the subject and message. +5. Click **Update** to save the template for the selected language. + +# Manage with a Server SDK {% #server-sdks %} + +You can also manage email templates programmatically using a [Server SDK](/docs/sdks#server). + +{% info title="Required scopes" %} +The API key used for these calls needs `templates.read` to list or fetch templates, and `templates.write` to update them. +{% /info %} + +## List email templates {% #list-email-templates %} + +You can paginate the result with the `limit` and `offset` queries. See [Queries](/docs/products/databases/queries) for the query syntax. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.listEmailTemplates({ + queries: [], // optional + total: false // optional +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.listEmailTemplates({ + queries: [], // optional + total: false // optional +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your API key + +$project = new Project($client); + +$result = $project->listEmailTemplates( + queries: [], // optional + total: false // optional +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import EmailTemplateList + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your API key + +project = Project(client) + +result: EmailTemplateList = project.list_email_templates( + queries = [], # optional + total = False # optional +) + +print(result.model_dump()) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your API key + +project = Project.new(client) + +result = project.list_email_templates( + queries: [], # optional + total: false # optional +) +``` +```server-dotnet +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 + .SetKey(""); // Your API key + +Project project = new Project(client); + +EmailTemplateList result = await project.ListEmailTemplates( + queries: new List(), // optional + total: false // optional +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +Project project = Project(client); + +EmailTemplateList result = await project.listEmailTemplates( + queries: [], // (optional) + total: false, // (optional) +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +val project = Project(client) + +val response = project.listEmailTemplates( + queries = listOf(), // optional + total = false // optional +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your API key + +Project project = new Project(client); + +project.listEmailTemplates( + List.of(), // queries (optional) + false, // total (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +let project = Project(client) + +let emailTemplateList = try await project.listEmailTemplates( + queries: [], // optional + total: false // optional +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.ListEmailTemplates( + appwrite.WithListEmailTemplatesQueries([]interface{}{}), + appwrite.WithListEmailTemplatesTotal(false), + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new(); + client.set_endpoint("https://.cloud.appwrite.io/v1"); // Your API Endpoint + client.set_project(""); // Your project ID + client.set_key(""); // Your API key + + let project = Project::new(&client); + + let result = project.list_email_templates( + Some(vec![]), // optional + Some(false) // optional + ).await?; + + let _ = result; + + Ok(()) +} +``` +```bash +appwrite project list-email-templates +``` +{% /multicode %} + +## Get an email template {% #get-email-template %} + +Retrieve a single template by its type and, optionally, locale. If you omit the locale, the fallback locale `en` is returned. + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectEmailTemplateId, ProjectEmailTemplateLocale } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.getEmailTemplate({ + templateId: ProjectEmailTemplateId.Verification, + locale: ProjectEmailTemplateLocale.En // optional +}); +``` +```server-deno +import { Client, Project, ProjectEmailTemplateId, ProjectEmailTemplateLocale } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.getEmailTemplate({ + templateId: ProjectEmailTemplateId.Verification, + locale: ProjectEmailTemplateLocale.En // optional +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your API key + +$project = new Project($client); + +$result = $project->getEmailTemplate( + templateId: ProjectEmailTemplateId::VERIFICATION(), + locale: ProjectEmailTemplateLocale::EN() // optional +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import EmailTemplate +from appwrite.enums import ProjectEmailTemplateId +from appwrite.enums import ProjectEmailTemplateLocale + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your API key + +project = Project(client) + +result: EmailTemplate = project.get_email_template( + template_id = ProjectEmailTemplateId.VERIFICATION, + locale = ProjectEmailTemplateLocale.EN # optional +) + +print(result.model_dump()) +``` +```server-ruby +require 'appwrite' + +include Appwrite +include Appwrite::Enums + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your API key + +project = Project.new(client) + +result = project.get_email_template( + template_id: ProjectEmailTemplateId::VERIFICATION, + locale: ProjectEmailTemplateLocale::EN # optional +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your API key + +Project project = new Project(client); + +EmailTemplate result = await project.GetEmailTemplate( + templateId: ProjectEmailTemplateId.Verification, + locale: ProjectEmailTemplateLocale.En // optional +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +Project project = Project(client); + +EmailTemplate result = await project.getEmailTemplate( + templateId: enums.ProjectEmailTemplateId.verification, + locale: enums.ProjectEmailTemplateLocale.en, // (optional) +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.enums.ProjectEmailTemplateId +import io.appwrite.enums.ProjectEmailTemplateLocale +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +val project = Project(client) + +val response = project.getEmailTemplate( + templateId = ProjectEmailTemplateId.VERIFICATION, + locale = ProjectEmailTemplateLocale.EN // optional +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.enums.ProjectEmailTemplateId; +import io.appwrite.enums.ProjectEmailTemplateLocale; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your API key + +Project project = new Project(client); + +project.getEmailTemplate( + ProjectEmailTemplateId.VERIFICATION, // templateId + ProjectEmailTemplateLocale.EN, // locale (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +let project = Project(client) + +let emailTemplate = try await project.getEmailTemplate( + templateId: .verification, + locale: .en // optional +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.GetEmailTemplate( + "verification", + appwrite.WithGetEmailTemplateLocale("en"), + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; +use appwrite::enums::ProjectEmailTemplateId; +use appwrite::enums::ProjectEmailTemplateLocale; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new(); + client.set_endpoint("https://.cloud.appwrite.io/v1"); // Your API Endpoint + client.set_project(""); // Your project ID + client.set_key(""); // Your API key + + let project = Project::new(&client); + + let result = project.get_email_template( + ProjectEmailTemplateId::Verification, + Some(ProjectEmailTemplateLocale::En) // optional + ).await?; + + let _ = result; + + Ok(()) +} +``` +```bash +appwrite project get-email-template \ + --template-id verification \ + --locale en +``` +{% /multicode %} + +## Update an email template {% #update-email-template %} + +Customize a template's subject, message, and sender identity for a given type and locale. Every field is optional, so you can change only the values you need. The `subject` and `message` accept the `{{user}}`, `{{project}}`, and `{{redirect}}` variables, which Appwrite replaces when sending the email. + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectEmailTemplateId, ProjectEmailTemplateLocale } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.updateEmailTemplate({ + templateId: ProjectEmailTemplateId.Verification, + locale: ProjectEmailTemplateLocale.En, // optional + subject: '', // optional + message: '', // optional + senderName: '', // optional + senderEmail: 'email@example.com', // optional + replyToEmail: 'email@example.com', // optional + replyToName: '' // optional +}); +``` +```server-deno +import { Client, Project, ProjectEmailTemplateId, ProjectEmailTemplateLocale } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.updateEmailTemplate({ + templateId: ProjectEmailTemplateId.Verification, + locale: ProjectEmailTemplateLocale.En, // optional + subject: '', // optional + message: '', // optional + senderName: '', // optional + senderEmail: 'email@example.com', // optional + replyToEmail: 'email@example.com', // optional + replyToName: '' // optional +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your API key + +$project = new Project($client); + +$result = $project->updateEmailTemplate( + templateId: ProjectEmailTemplateId::VERIFICATION(), + locale: ProjectEmailTemplateLocale::EN(), // optional + subject: '', // optional + message: '', // optional + senderName: '', // optional + senderEmail: 'email@example.com', // optional + replyToEmail: 'email@example.com', // optional + replyToName: '' // optional +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import EmailTemplate +from appwrite.enums import ProjectEmailTemplateId +from appwrite.enums import ProjectEmailTemplateLocale + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your API key + +project = Project(client) + +result: EmailTemplate = project.update_email_template( + template_id = ProjectEmailTemplateId.VERIFICATION, + locale = ProjectEmailTemplateLocale.EN, # optional + subject = '', # optional + message = '', # optional + sender_name = '', # optional + sender_email = 'email@example.com', # optional + reply_to_email = 'email@example.com', # optional + reply_to_name = '' # optional +) + +print(result.model_dump()) +``` +```server-ruby +require 'appwrite' + +include Appwrite +include Appwrite::Enums + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your API key + +project = Project.new(client) + +result = project.update_email_template( + template_id: ProjectEmailTemplateId::VERIFICATION, + locale: ProjectEmailTemplateLocale::EN, # optional + subject: '', # optional + message: '', # optional + sender_name: '', # optional + sender_email: 'email@example.com', # optional + reply_to_email: 'email@example.com', # optional + reply_to_name: '' # optional +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your API key + +Project project = new Project(client); + +EmailTemplate result = await project.UpdateEmailTemplate( + templateId: ProjectEmailTemplateId.Verification, + locale: ProjectEmailTemplateLocale.En, // optional + subject: "", // optional + message: "", // optional + senderName: "", // optional + senderEmail: "email@example.com", // optional + replyToEmail: "email@example.com", // optional + replyToName: "" // optional +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +Project project = Project(client); + +EmailTemplate result = await project.updateEmailTemplate( + templateId: enums.ProjectEmailTemplateId.verification, + locale: enums.ProjectEmailTemplateLocale.en, // (optional) + subject: '', // (optional) + message: '', // (optional) + senderName: '', // (optional) + senderEmail: 'email@example.com', // (optional) + replyToEmail: 'email@example.com', // (optional) + replyToName: '', // (optional) +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.enums.ProjectEmailTemplateId +import io.appwrite.enums.ProjectEmailTemplateLocale +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +val project = Project(client) + +val response = project.updateEmailTemplate( + templateId = ProjectEmailTemplateId.VERIFICATION, + locale = ProjectEmailTemplateLocale.EN, // optional + subject = "", // optional + message = "", // optional + senderName = "", // optional + senderEmail = "email@example.com", // optional + replyToEmail = "email@example.com", // optional + replyToName = "" // optional +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.enums.ProjectEmailTemplateId; +import io.appwrite.enums.ProjectEmailTemplateLocale; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your API key + +Project project = new Project(client); + +project.updateEmailTemplate( + ProjectEmailTemplateId.VERIFICATION, // templateId + ProjectEmailTemplateLocale.EN, // locale (optional) + "", // subject (optional) + "", // message (optional) + "", // senderName (optional) + "email@example.com", // senderEmail (optional) + "email@example.com", // replyToEmail (optional) + "", // replyToName (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +let project = Project(client) + +let emailTemplate = try await project.updateEmailTemplate( + templateId: .verification, + locale: .en, // optional + subject: "", // optional + message: "", // optional + senderName: "", // optional + senderEmail: "email@example.com", // optional + replyToEmail: "email@example.com", // optional + replyToName: "" // optional +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.UpdateEmailTemplate( + "verification", + appwrite.WithUpdateEmailTemplateLocale("en"), + appwrite.WithUpdateEmailTemplateSubject(""), + appwrite.WithUpdateEmailTemplateMessage(""), + appwrite.WithUpdateEmailTemplateSenderName(""), + appwrite.WithUpdateEmailTemplateSenderEmail("email@example.com"), + appwrite.WithUpdateEmailTemplateReplyToEmail("email@example.com"), + appwrite.WithUpdateEmailTemplateReplyToName(""), + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; +use appwrite::enums::ProjectEmailTemplateId; +use appwrite::enums::ProjectEmailTemplateLocale; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new(); + client.set_endpoint("https://.cloud.appwrite.io/v1"); // Your API Endpoint + client.set_project(""); // Your project ID + client.set_key(""); // Your API key + + let project = Project::new(&client); + + let result = project.update_email_template( + ProjectEmailTemplateId::Verification, + Some(ProjectEmailTemplateLocale::En), // optional + Some(""), // optional + Some(""), // optional + Some(""), // optional + Some("email@example.com"), // optional + Some("email@example.com"), // optional + Some("") // optional + ).await?; + + let _ = result; + + Ok(()) +} +``` +```bash +appwrite project update-email-template \ + --template-id verification \ + --locale en \ + --subject "" \ + --message "" \ + --sender-name "" \ + --sender-email email@example.com \ + --reply-to-email email@example.com \ + --reply-to-name "" +``` +{% /multicode %} + +# Template types {% #template-types %} + +Each email template is identified by a `templateId`. The available types map to the account management emails Appwrite sends: + +| Console name | Template ID | Sent when | +|------------------|----------------|------------------------------------------------------------| +| Verification | `verification` | A user requests email address verification. | +| Magic URL | `magicSession` | A user signs in with a magic URL link. | +| OTP session | `otpSession` | A user signs in with an email one-time password. | +| Reset password | `recovery` | A user starts the password recovery flow. | +| Invite user | `invitation` | A user is invited to join a team. | +| 2FA verification | `mfaChallenge` | A user completes an email-based multi-factor challenge. | +| Session alert | `sessionAlert` | A new session is created on a user's account. | + +# Locales {% #locales %} + +Templates are stored per locale, so you can send the right copy to each audience. Pass the `locale` parameter to read or write the version for a specific language. If you omit it, Appwrite uses the fallback locale `en`. Locale codes follow the ISO 639-1 standard with optional region suffixes, such as `en`, `fr`, `de`, or `pt-br`. + +# Benefits {% #benefits %} + +- **On-brand emails.** Replace the default sender name, address, subject, and message so account emails match your product instead of generic Appwrite copy. +- **Localized messaging.** Maintain a separate version of each template per locale and reach every user in their own language. +- **Repeatable provisioning.** Script template content as code and apply the same configuration across dev, staging, and production projects without clicking through the Console. diff --git a/src/routes/docs/advanced/platform/environment-variables/+page.markdoc b/src/routes/docs/platforms/project/environment-variables/+page.markdoc similarity index 99% rename from src/routes/docs/advanced/platform/environment-variables/+page.markdoc rename to src/routes/docs/platforms/project/environment-variables/+page.markdoc index c61134bc0cb..fe309d414b5 100644 --- a/src/routes/docs/advanced/platform/environment-variables/+page.markdoc +++ b/src/routes/docs/platforms/project/environment-variables/+page.markdoc @@ -52,7 +52,11 @@ You can create and manage project variables from the Appwrite Console. The Conso # Manage with a Server SDK {% #server-sdks %} -You can also manage project variables programmatically using a [Server SDK](/docs/sdks#server). Each call requires an [API key](/docs/advanced/platform/api-keys) with the `project.write` scope to create, update, or delete variables, or the `project.read` scope to list and read them. +You can also manage project variables programmatically using a [Server SDK](/docs/sdks#server). + +{% info title="Required scopes" %} +The API key used for these calls needs `project.read` to list or fetch variables, and `project.write` to create, update, or delete them. +{% /info %} ## Create a variable {% #create-variable %} diff --git a/src/routes/docs/platforms/project/labels/+page.markdoc b/src/routes/docs/platforms/project/labels/+page.markdoc new file mode 100644 index 00000000000..a8272414508 --- /dev/null +++ b/src/routes/docs/platforms/project/labels/+page.markdoc @@ -0,0 +1,270 @@ +--- +layout: article +title: Labels +description: Assign customizable labels to your Appwrite project to categorize and filter projects within an organization. +--- + +Labels are short alphanumeric tags you assign to a project. Use them to categorize your projects and filter them within an organization, for example by environment (`production`, `staging`), team, or region. + +# Manage in the Console {% #console %} + +{% only_dark %} +![Project labels in the Appwrite Console](/images/docs/project/dark/labels.avif) +{% /only_dark %} +{% only_light %} +![Project labels in the Appwrite Console](/images/docs/project/labels.avif) +{% /only_light %} + +To manage labels from the Appwrite Console: + +1. Navigate to your project. +2. Open the **Settings** section. The **Labels** card is on the **Overview** tab. +3. In the **Labels** field, type a label and press Enter, or select one of the suggested labels. Labels may contain only alphanumeric characters. +4. Click **Update** to save your changes. + +# Manage with a Server SDK {% #server-sdks %} + +You can also manage project labels programmatically using a [Server SDK](/docs/sdks#server). + +{% info title="Required scope" %} +The API key used for this call needs the `project.write` scope. +{% /info %} + +## Update labels {% #update-labels %} + +The `labels` array replaces the project's existing labels, so include every label you want to keep in each call. A project can have up to 1000 labels, each up to 36 alphanumeric characters long. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.updateLabels({ + labels: ['production', 'eu'] +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.updateLabels({ + labels: ['production', 'eu'] +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your API key + +$project = new Project($client); + +$result = $project->updateLabels( + labels: ['production', 'eu'] +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import Project as ProjectModel + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your API key + +project = Project(client) + +result: ProjectModel = project.update_labels( + labels = ['production', 'eu'] +) + +print(result.model_dump()) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your API key + +project = Project.new(client) + +result = project.update_labels( + labels: ['production', 'eu'] +) +``` +```server-dotnet +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 + .SetKey(""); // Your API key + +Project project = new Project(client); + +Project result = await project.UpdateLabels( + labels: new List { "production", "eu" } +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +Project project = Project(client); + +Project result = await project.updateLabels( + labels: ['production', 'eu'], +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +val project = Project(client) + +val response = project.updateLabels( + labels = listOf("production", "eu") +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your API key + +Project project = new Project(client); + +project.updateLabels( + List.of("production", "eu"), // labels + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +let project = Project(client) + +let result = try await project.updateLabels( + labels: ["production", "eu"] +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.UpdateLabels( + []interface{}{"production", "eu"}, + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new(); + client.set_endpoint("https://.cloud.appwrite.io/v1"); // Your API Endpoint + client.set_project(""); // Your project ID + client.set_key(""); // Your API key + + let project = Project::new(&client); + + let result = project.update_labels( + vec!["production", "eu"] + ).await?; + + let _ = result; + + Ok(()) +} +``` +```bash +appwrite project update-labels \ + --labels production \ + --labels eu +``` +{% /multicode %} + +{% info title="Reading labels" %} +Labels have no dedicated read endpoint. Call `get` to fetch the project and read its `labels` field. + +```server-nodejs +const result = await project.get(); +console.log(result.labels); // ['production', 'eu'] +``` +{% /info %} + +# Benefits {% #benefits %} + +- **Organize at scale.** Group related projects with shared tags such as environment, team, or region, so large organizations stay navigable. +- **Faster filtering.** Find the projects you need by filtering an organization on its labels instead of scanning the full list. +- **Repeatable provisioning.** Apply a consistent labeling scheme across projects from a script, keeping your organization tidy without manual Console work. diff --git a/src/routes/docs/platforms/project/mock-phones/+page.markdoc b/src/routes/docs/platforms/project/mock-phones/+page.markdoc new file mode 100644 index 00000000000..5f52881eee5 --- /dev/null +++ b/src/routes/docs/platforms/project/mock-phones/+page.markdoc @@ -0,0 +1,1098 @@ +--- +layout: article +title: Mock phones +description: Register fictional phone numbers and OTPs to test phone authentication flows without sending real SMS messages. +--- + +Mock phones let you register fictional phone numbers and a fixed verification code at the project level. When a tester signs in with a registered number, the registered code works in place of a real SMS, so phone authentication flows can be exercised in CI, demo accounts, and app store review submissions without sending SMS or paying provider fees. + +Each project stores its mock phones on the project document. Numbers must be in [E.164](https://en.wikipedia.org/wiki/E.164) format, and verification codes are exactly six digits. + +# Add from the Console {% #toggle-console %} + +{% only_dark %} +![Mock phone numbers settings in the Appwrite Console](/images/docs/project/dark/mock-phones.avif) +{% /only_dark %} +{% only_light %} +![Mock phone numbers settings in the Appwrite Console](/images/docs/project/mock-phones.avif) +{% /only_light %} + +To add a mock phone manually: + +1. Open your project in the Appwrite Console. +2. Navigate to **Auth** in the sidebar, then open the **Settings** tab. +3. Scroll to the **Mock phone numbers** card and click **Add a number**. +4. Enter a phone number in E.164 format (for example, `+15555550100`) and a six-digit verification code. +5. Click **Save** on the row, then **Update** at the bottom of the section to persist. + +Use fictional ranges (such as North American `555` numbers) to avoid collision with real subscribers. + +# Manage with a Server SDK {% #manage-with-sdk %} + +The Project service exposes endpoints to list, create, get, update, and delete mock phones. All endpoints require an API key with the appropriate scope or a Console session. + +{% info title="Required scopes" %} +Reading mock phones requires the `mocks.read` scope. Creating, updating, or deleting requires `mocks.write`. +{% /info %} + +## Create a mock phone {% #create-mock-phone %} + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.createMockPhone({ + number: '+15555550100', + otp: '123456' +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.createMockPhone({ + number: '+15555550100', + otp: '123456' +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->createMockPhone( + number: '+15555550100', + otp: '123456' +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.create_mock_phone( + number = '+15555550100', + otp = '123456' +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +result = project.create_mock_phone( + number: '+15555550100', + otp: '123456' +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.CreateMockPhone( + number: "+15555550100", + otp: "123456" +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.createMockPhone( + number: '+15555550100', + otp: '123456', +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val result = project.createMockPhone( + number = "+15555550100", + otp = "123456" +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.createMockPhone( + "+15555550100", // number + "123456", // otp + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.createMockPhone( + number: "+15555550100", + otp: "123456" +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.CreateMockPhone( + "+15555550100", + "123456", + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.create_mock_phone( + "+15555550100", + "123456", + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project create-mock-phone \ + --number +15555550100 \ + --otp 123456 +``` +{% /multicode %} + +The endpoint returns the new [MockNumber](/docs/references/cloud/models/mockNumber) document. + +## List mock phones {% #list-mock-phones %} + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.listMockPhones(); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.listMockPhones(); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->listMockPhones(); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.list_mock_phones() +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +result = project.list_mock_phones() +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.ListMockPhones(); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.listMockPhones(); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val result = project.listMockPhones() +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.listMockPhones(new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); +})); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.listMockPhones() +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.ListMockPhones() + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.list_mock_phones(None, None).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project list-mock-phones \ + --limit 25 +``` +{% /multicode %} + +## Get a mock phone {% #get-mock-phone %} + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.getMockPhone({ + number: '+15555550100' +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.getMockPhone({ + number: '+15555550100' +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->getMockPhone( + number: '+15555550100' +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.get_mock_phone( + number = '+15555550100' +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +result = project.get_mock_phone( + number: '+15555550100' +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.GetMockPhone( + number: "+15555550100" +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.getMockPhone( + number: '+15555550100', +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val result = project.getMockPhone( + number = "+15555550100" +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.getMockPhone( + "+15555550100", // number + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.getMockPhone( + number: "+15555550100" +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.GetMockPhone("+15555550100") + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.get_mock_phone("+15555550100").await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project get-mock-phone --number +15555550100 +``` +{% /multicode %} + +## Update a mock phone {% #update-mock-phone %} + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateMockPhone({ + number: '+15555550100', + otp: '654321' +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateMockPhone({ + number: '+15555550100', + otp: '654321' +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateMockPhone( + number: '+15555550100', + otp: '654321' +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_mock_phone( + number = '+15555550100', + otp = '654321' +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +result = project.update_mock_phone( + number: '+15555550100', + otp: '654321' +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateMockPhone( + number: "+15555550100", + otp: "654321" +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateMockPhone( + number: '+15555550100', + otp: '654321', +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val result = project.updateMockPhone( + number = "+15555550100", + otp = "654321" +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateMockPhone( + "+15555550100", // number + "654321", // otp + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateMockPhone( + number: "+15555550100", + otp: "654321" +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.UpdateMockPhone("+15555550100", "654321") + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_mock_phone("+15555550100", "654321").await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-mock-phone \ + --number +15555550100 \ + --otp 654321 +``` +{% /multicode %} + +## Delete a mock phone {% #delete-mock-phone %} + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +await project.deleteMockPhone({ + number: '+15555550100' +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +await project.deleteMockPhone({ + number: '+15555550100' +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$project->deleteMockPhone( + number: '+15555550100' +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +project.delete_mock_phone( + number = '+15555550100' +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +project.delete_mock_phone( + number: '+15555550100' +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +await project.DeleteMockPhone( + number: "+15555550100" +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +await project.deleteMockPhone( + number: '+15555550100', +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +project.deleteMockPhone( + number = "+15555550100" +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.deleteMockPhone( + "+15555550100", // number + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +try await project.deleteMockPhone( + number: "+15555550100" +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + _, err := project.DeleteMockPhone("+15555550100") + + if err != nil { + panic(err) + } + + fmt.Println("deleted") +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + project.delete_mock_phone("+15555550100").await?; + + Ok(()) +} +``` +```bash +appwrite project delete-mock-phone --number +15555550100 +``` +{% /multicode %} + +# Benefits {% #benefits %} + +- **No SMS costs in test flows.** Exercise phone authentication in CI, demo accounts, and app store review submissions without sending real SMS or paying provider fees. +- **Stable credentials for automation.** Registered numbers and codes don't expire or rotate, so end-to-end tests stay deterministic across runs. +- **Repeatable provisioning.** Script the mock phone set a project should expose and apply it from CI when spinning up a new environment. diff --git a/src/routes/docs/platforms/project/oauth/+page.markdoc b/src/routes/docs/platforms/project/oauth/+page.markdoc new file mode 100644 index 00000000000..6f837f3880b --- /dev/null +++ b/src/routes/docs/platforms/project/oauth/+page.markdoc @@ -0,0 +1,1060 @@ +--- +layout: article +title: OAuth providers +description: Configure OAuth2 sign-in providers for your project from the Console or programmatically with a Server SDK. +--- + +OAuth2 providers let your users sign in with accounts they already have, such as GitHub, Google, or Apple. Each provider stores a client ID and client secret at the project level, and can be enabled or disabled independently. + +You can configure providers from the Appwrite Console or programmatically with a [Server SDK](/docs/sdks#server). Each provider has its own update method (`updateOAuth2GitHub`, `updateOAuth2Google`, and so on), the read methods `listOAuth2Providers` and `getOAuth2Provider` cover all of them. + +# Configure from the Console {% #configure-console %} + +{% only_dark %} +![OAuth2 providers in the Appwrite Console](/images/docs/project/dark/oauth-providers.avif) +{% /only_dark %} +{% only_light %} +![OAuth2 providers in the Appwrite Console](/images/docs/project/oauth-providers.avif) +{% /only_light %} + +To configure a provider from the Console: + +1. Open your project in the Appwrite Console. +2. Navigate to **Auth** in the sidebar, then open the **Settings** tab. +3. Find the provider in the **OAuth2 Providers** list and click it. +4. Enter the credentials from the provider (the field names vary per provider, see [Available providers](#available-providers)). +5. Toggle the provider on and click **Update**. + +# Configure a provider {% #configure-provider %} + +Each provider has a dedicated update method named `updateOAuth2`. The example below configures GitHub. Swap the method name and credential fields to configure a different provider, the field names per provider are listed in [Available providers](#available-providers). + +{% info title="Required scopes" %} +The API key used for these calls needs `oauth2.write` to configure providers, and `oauth2.read` to list or fetch them. +{% /info %} + +{% info title="Enabling validates credentials" %} +Setting `enabled` to `true` triggers end-to-end validation of the credentials against the provider, and the request throws if they are invalid. To store credentials without activating the provider yet, send them with `enabled` set to `false`. +{% /info %} + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateOAuth2GitHub({ + clientId: '', + clientSecret: '', + enabled: true +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateOAuth2GitHub({ + clientId: '', + clientSecret: '', + enabled: true +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateOAuth2GitHub( + clientId: '', + clientSecret: '', + enabled: true +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_o_auth2_git_hub( + client_id = '', + client_secret = '', + enabled = True +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_o_auth2_git_hub( + client_id: '', + client_secret: '', + enabled: true +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateOAuth2GitHub( + clientId: "", + clientSecret: "", + enabled: true +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateOAuth2GitHub( + clientId: '', + clientSecret: '', + enabled: true, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateOAuth2GitHub( + clientId = "", + clientSecret = "", + enabled = true +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateOAuth2GitHub( + "", // clientId + "", // clientSecret + true, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateOAuth2GitHub( + clientId: "", + clientSecret: "", + enabled: true +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateOAuth2GitHub( + service.WithUpdateOAuth2GitHubClientId(""), + service.WithUpdateOAuth2GitHubClientSecret(""), + service.WithUpdateOAuth2GitHubEnabled(true), + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_o_auth2_git_hub( + Some(""), + Some(""), + Some(true), + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-o-auth-2-git-hub \ + --client-id "" \ + --client-secret "" \ + --enabled true +``` +{% /multicode %} + +## Providers with extra fields {% #provider-extra-fields %} + +Some providers take more than a client ID and secret. Google, for example, accepts an additional `prompt` parameter that controls the consent screen behavior: + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectOAuth2GooglePrompt } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateOAuth2Google({ + clientId: '', + clientSecret: '', + prompt: [ProjectOAuth2GooglePrompt.SelectAccount], + enabled: true +}); +``` +```server-deno +import { Client, Project, ProjectOAuth2GooglePrompt } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateOAuth2Google({ + clientId: '', + clientSecret: '', + prompt: [ProjectOAuth2GooglePrompt.SelectAccount], + enabled: true +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateOAuth2Google( + clientId: '', + clientSecret: '', + prompt: [ProjectOAuth2GooglePrompt::SELECTACCOUNT()], + enabled: true +); +``` +```server-python +from appwrite.client import Client +from appwrite.enums import ProjectOAuth2GooglePrompt +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_o_auth2_google( + client_id = '', + client_secret = '', + prompt = [ProjectOAuth2GooglePrompt.SELECT_ACCOUNT], + enabled = True +) +``` +```server-ruby +require 'appwrite' + +include Appwrite +include Appwrite::Enums + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_o_auth2_google( + client_id: '', + client_secret: '', + prompt: [ProjectOAuth2GooglePrompt::SELECT_ACCOUNT], + enabled: true +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateOAuth2Google( + clientId: "", + clientSecret: "", + prompt: new List {ProjectOAuth2GooglePrompt.SelectAccount}, + enabled: true +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateOAuth2Google( + clientId: '', + clientSecret: '', + prompt: [enums.ProjectOAuth2GooglePrompt.selectAccount], + enabled: true, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.enums.ProjectOAuth2GooglePrompt +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateOAuth2Google( + clientId = "", + clientSecret = "", + prompt = listOf(ProjectOAuth2GooglePrompt.SELECT_ACCOUNT), + enabled = true +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.enums.ProjectOAuth2GooglePrompt; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateOAuth2Google( + "", // clientId + "", // clientSecret + listOf(ProjectOAuth2GooglePrompt.SELECT_ACCOUNT), // prompt + true, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateOAuth2Google( + clientId: "", + clientSecret: "", + prompt: [.selectAccount], + enabled: true +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateOAuth2Google( + service.WithUpdateOAuth2GoogleClientId(""), + service.WithUpdateOAuth2GoogleClientSecret(""), + service.WithUpdateOAuth2GooglePrompt([]string{"select_account"}), + service.WithUpdateOAuth2GoogleEnabled(true), + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::enums::ProjectOAuth2GooglePrompt; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_o_auth2_google( + Some(""), + Some(""), + Some(vec![ProjectOAuth2GooglePrompt::SelectAccount]), + Some(true), + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-o-auth-2-google \ + --client-id "" \ + --client-secret "" \ + --prompt "select_account" \ + --enabled true +``` +{% /multicode %} + +# Available providers {% #available-providers %} + +Every provider has its own `updateOAuth2` method. The credential field names differ per provider, use the columns below to map the provider's credentials to the method's parameters. + +| Provider | SDK method | App ID field | App secret field | Other fields | +| --- | --- | --- | --- | --- | +| Amazon | `updateOAuth2Amazon` | `clientId` | `clientSecret` | | +| Apple | `updateOAuth2Apple` | `serviceId` | `keyId` | `teamId` | +| Auth0 | `updateOAuth2Auth0` | `clientId` | `clientSecret` | `endpoint` | +| Authentik | `updateOAuth2Authentik` | `clientId` | `clientSecret` | `endpoint` | +| Autodesk | `updateOAuth2Autodesk` | `clientId` | `clientSecret` | | +| Bitbucket | `updateOAuth2Bitbucket` | `key` | `secret` | | +| Bitly | `updateOAuth2Bitly` | `clientId` | `clientSecret` | | +| Box | `updateOAuth2Box` | `clientId` | `clientSecret` | | +| Dailymotion | `updateOAuth2Dailymotion` | `apiKey` | `apiSecret` | | +| Discord | `updateOAuth2Discord` | `clientId` | `clientSecret` | | +| Disqus | `updateOAuth2Disqus` | `publicKey` | `secretKey` | | +| Dropbox | `updateOAuth2Dropbox` | `appKey` | `appSecret` | | +| Etsy | `updateOAuth2Etsy` | `keyString` | `sharedSecret` | | +| Facebook | `updateOAuth2Facebook` | `appId` | `appSecret` | | +| Figma | `updateOAuth2Figma` | `clientId` | `clientSecret` | | +| FusionAuth | `updateOAuth2FusionAuth` | `clientId` | `clientSecret` | `endpoint` | +| GitHub | `updateOAuth2GitHub` | `clientId` | `clientSecret` | | +| GitLab | `updateOAuth2Gitlab` | `applicationId` | `secret` | `endpoint` | +| Google | `updateOAuth2Google` | `clientId` | `clientSecret` | `prompt` | +| Keycloak | `updateOAuth2Keycloak` | `clientId` | `clientSecret` | `endpoint`, `realmName` | +| Kick | `updateOAuth2Kick` | `clientId` | `clientSecret` | | +| LinkedIn | `updateOAuth2Linkedin` | `clientId` | `primaryClientSecret` | | +| Microsoft | `updateOAuth2Microsoft` | `applicationId` | `applicationSecret` | `tenant` | +| Notion | `updateOAuth2Notion` | `oauthClientId` | `oauthClientSecret` | | +| OIDC | `updateOAuth2Oidc` | `clientId` | `clientSecret` | `wellKnownURL`, `authorizationURL`, `tokenURL`, `userInfoURL` | +| Okta | `updateOAuth2Okta` | `clientId` | `clientSecret` | `domain`, `authorizationServerId` | +| PayPal | `updateOAuth2Paypal` | `clientId` | `secretKey` | | +| PayPal Sandbox | `updateOAuth2PaypalSandbox` | `clientId` | `secretKey` | | +| Podio | `updateOAuth2Podio` | `clientId` | `clientSecret` | | +| Salesforce | `updateOAuth2Salesforce` | `customerKey` | `customerSecret` | | +| Slack | `updateOAuth2Slack` | `clientId` | `clientSecret` | | +| Spotify | `updateOAuth2Spotify` | `clientId` | `clientSecret` | | +| Stripe | `updateOAuth2Stripe` | `clientId` | `apiSecretKey` | | +| Tradeshift | `updateOAuth2Tradeshift` | | | `enabled` only | +| Tradeshift Sandbox | `updateOAuth2TradeshiftSandbox` | | | `enabled` only | +| Twitch | `updateOAuth2Twitch` | `clientId` | `clientSecret` | | +| WordPress | `updateOAuth2WordPress` | `clientId` | `clientSecret` | | +| X | `updateOAuth2X` | `customerKey` | `secretKey` | | +| Yahoo | `updateOAuth2Yahoo` | `clientId` | `clientSecret` | | +| Yandex | `updateOAuth2Yandex` | `clientId` | `clientSecret` | | +| Zoho | `updateOAuth2Zoho` | `clientId` | `clientSecret` | | +| Zoom | `updateOAuth2Zoom` | `clientId` | `clientSecret` | | + +{% info title="Apple is in beta" %} +The Apple provider is currently in beta. +{% /info %} + +# List providers {% #list-providers %} + +List every OAuth2 provider and its current configuration state. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.listOAuth2Providers({ + queries: [], + total: false +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.listOAuth2Providers({ + queries: [], + total: false +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->listOAuth2Providers( + queries: [], + total: false +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.list_o_auth2_providers( + queries = [], + total = False +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.list_o_auth2_providers( + queries: [], + total: false +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.ListOAuth2Providers( + queries: new List(), + total: false +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.listOAuth2Providers( + queries: [], + total: false, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.listOAuth2Providers( + queries = listOf(), + total = false +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.listOAuth2Providers( + List.of(), // queries + false, // total + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.listOAuth2Providers( + queries: [], + total: false +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.ListOAuth2Providers( + service.WithListOAuth2ProvidersQueries([]string{}), + service.WithListOAuth2ProvidersTotal(false), + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.list_o_auth2_providers( + Some(vec![]), + Some(false), + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project list-o-auth-2-providers \ + --limit 25 +``` +{% /multicode %} + +# Get a provider {% #get-provider %} + +Fetch a single provider's configuration by its provider ID. + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectOAuthProviderId } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.getOAuth2Provider({ + providerId: ProjectOAuthProviderId.Github +}); +``` +```server-deno +import { Client, Project, ProjectOAuthProviderId } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.getOAuth2Provider({ + providerId: ProjectOAuthProviderId.Github +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->getOAuth2Provider( + providerId: ProjectOAuthProviderId::GITHUB() +); +``` +```server-python +from appwrite.client import Client +from appwrite.enums import ProjectOAuthProviderId +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.get_o_auth2_provider( + provider_id = ProjectOAuthProviderId.GITHUB +) +``` +```server-ruby +require 'appwrite' + +include Appwrite +include Appwrite::Enums + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.get_o_auth2_provider( + provider_id: ProjectOAuthProviderId::GITHUB +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.GetOAuth2Provider( + providerId: ProjectOAuthProviderId.Github +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.getOAuth2Provider( + providerId: enums.ProjectOAuthProviderId.github, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.enums.ProjectOAuthProviderId +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.getOAuth2Provider( + providerId = ProjectOAuthProviderId.GITHUB +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.enums.ProjectOAuthProviderId; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.getOAuth2Provider( + ProjectOAuthProviderId.GITHUB, // providerId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.getOAuth2Provider( + providerId: .github +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.GetOAuth2Provider( + "github", + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::enums::ProjectOAuthProviderId; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.get_o_auth2_provider( + ProjectOAuthProviderId::Github, + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project get-o-auth-2-provider \ + --provider-id github +``` +{% /multicode %} + +# Benefits {% #benefits %} + +- **Repeatable provisioning.** Script the full set of OAuth2 providers a project needs and recreate it on demand, without clicking through the Console. +- **Environment parity.** Keep dev, staging, and production projects in sync by running the same configuration script against each one. +- **Server-only secrets.** Client secrets are write-only over the API and never returned in responses, so configuration scripts can run in CI without exposing them. diff --git a/src/routes/docs/platforms/project/platforms/+page.markdoc b/src/routes/docs/platforms/project/platforms/+page.markdoc new file mode 100644 index 00000000000..d2aa0da8454 --- /dev/null +++ b/src/routes/docs/platforms/project/platforms/+page.markdoc @@ -0,0 +1,1206 @@ +--- +layout: article +title: Platforms +description: Register Web, Apple, Android, Windows, and Linux apps to your Appwrite project programmatically using server SDKs. +--- + +Each Appwrite project has a list of registered platforms. A platform identifies a client application that is allowed to talk to your project's API: a Web platform pins an allowed hostname for CORS, while Apple, Android, Windows, and Linux platforms pin a bundle, package, or application ID for native clients. + +Platforms can be added from the Appwrite Console, or programmatically through any server SDK using the Project service. + +# Manage from the Console {% #manage-console %} + +{% only_dark %} +![Project platforms in the Appwrite Console](/images/docs/project/dark/platforms.avif) +{% /only_dark %} +{% only_light %} +![Project platforms in the Appwrite Console](/images/docs/project/platforms.avif) +{% /only_light %} + +To add a platform manually: + +1. Open your project in the Appwrite Console. +2. On the project **Overview**, scroll to the **Integrations** card and select the **Platforms** tab. +3. Click **Add platform** and choose the platform type (Web, Flutter, Android, Apple, or React Native). +4. Fill in the name and the platform's identifier (hostname for Web, bundle or package ID for native), then click **Create platform**. +5. To rename or remove a platform later, click its row and use the edit dialog or the **Delete** button. + +# Platform types {% #platform-types %} + +The Project service exposes a dedicated create method per platform type. Each method takes a unique `platformId`, a display `name`, and the platform's identifier: + +| Type | Method | Identifier param | +| --- | --- | --- | +| Web | `createWebPlatform` | `hostname` (e.g. `app.example.com`) | +| Apple | `createApplePlatform` | `bundleIdentifier` (e.g. `com.example.app`) | +| Android | `createAndroidPlatform` | `applicationId` (e.g. `com.example.app`) | +| Windows | `createWindowsPlatform` | `packageIdentifierName` | +| Linux | `createLinuxPlatform` | `packageName` | + +Flutter and React Native platforms shown in the Console map to the underlying Apple, Android, or Web type based on the target you pick. + +# Register a platform {% #register-platform %} + +The example below registers a Web platform. Swap the method name and identifier param to register Apple, Android, Windows, or Linux platforms. + +{% info title="Required scopes" %} +The API key used for these calls needs `platforms.write` to create, update, or delete platforms, and `platforms.read` to list or fetch them. +{% /info %} + +{% multicode %} +```server-nodejs +import { Client, Project, ID } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.createWebPlatform({ + platformId: ID.unique(), + name: 'My Web App', + hostname: 'app.example.com' +}); +``` +```server-deno +import { Client, Project, ID } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.createWebPlatform({ + platformId: ID.unique(), + name: 'My Web App', + hostname: 'app.example.com' +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->createWebPlatform( + platformId: ID::unique(), + name: 'My Web App', + hostname: 'app.example.com' +); +``` +```server-python +from appwrite.client import Client +from appwrite.id import ID +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.create_web_platform( + platform_id = ID.unique(), + name = 'My Web App', + hostname = 'app.example.com' +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.create_web_platform( + platform_id: ID.unique(), + name: 'My Web App', + hostname: 'app.example.com' +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.CreateWebPlatform( + platformId: ID.Unique(), + name: "My Web App", + hostname: "app.example.com" +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.createWebPlatform( + platformId: ID.unique(), + name: 'My Web App', + hostname: 'app.example.com', +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.ID +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.createWebPlatform( + platformId = ID.unique(), + name = "My Web App", + hostname = "app.example.com" +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.ID; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.createWebPlatform( + ID.unique(), // platformId + "My Web App", // name + "app.example.com", // hostname + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.createWebPlatform( + platformId: ID.unique(), + name: "My Web App", + hostname: "app.example.com" +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" + "github.com/appwrite/sdk-for-go/id" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.CreateWebPlatform( + id.Unique(), + "My Web App", + "app.example.com", + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::id::ID; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.create_web_platform( + ID::unique(), + "My Web App", + "app.example.com", + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project create-web-platform \ + --platform-id 'unique()' \ + --name "My Web App" \ + --hostname app.example.com +``` +{% /multicode %} + +# List platforms {% #list-platforms %} + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.listPlatforms({ + queries: [], + total: false +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.listPlatforms({ + queries: [], + total: false +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->listPlatforms( + queries: [], + total: false +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.list_platforms( + queries = [], + total = False +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.list_platforms( + queries: [], + total: false +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.ListPlatforms( + queries: new List(), + total: false +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.listPlatforms( + queries: [], + total: false, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.listPlatforms( + queries = listOf(), + total = false +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.listPlatforms( + List.of(), // queries + false, // total + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.listPlatforms( + queries: [], + total: false +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" + "github.com/appwrite/sdk-for-go/project" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.ListPlatforms( + project.WithListPlatformsQueries([]interface{}{}), + project.WithListPlatformsTotal(false), + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.list_platforms( + Some(vec![]), + Some(false), + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project list-platforms \ + --limit 25 +``` +{% /multicode %} + +# Get a platform {% #get-platform %} + +Fetch a single platform by its ID. The response includes the platform's type-specific fields, such as `hostname` for Web or `bundleIdentifier` for Apple. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.getPlatform({ + platformId: '' +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.getPlatform({ + platformId: '' +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->getPlatform( + platformId: '' +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.get_platform( + platform_id = '' +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +result = project.get_platform( + platform_id: '' +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.GetPlatform( + platformId: "" +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.getPlatform( + platformId: '', +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val result = project.getPlatform( + platformId = "" +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.getPlatform( + "", // platformId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.getPlatform( + platformId: "" +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.GetPlatform( + "", + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.get_platform( + "", + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project get-platform \ + --platform-id +``` +{% /multicode %} + +# Update a platform {% #update-platform %} + +Each platform type has a matching update method (`updateWebPlatform`, `updateApplePlatform`, and so on). The example below updates a Web platform's name and hostname. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateWebPlatform({ + platformId: '', + name: 'Renamed Web App', + hostname: 'app.example.com' +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateWebPlatform({ + platformId: '', + name: 'Renamed Web App', + hostname: 'app.example.com' +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateWebPlatform( + platformId: '', + name: 'Renamed Web App', + hostname: 'app.example.com' +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_web_platform( + platform_id = '', + name = 'Renamed Web App', + hostname = 'app.example.com' +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_web_platform( + platform_id: '', + name: 'Renamed Web App', + hostname: 'app.example.com' +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateWebPlatform( + platformId: "", + name: "Renamed Web App", + hostname: "app.example.com" +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateWebPlatform( + platformId: '', + name: 'Renamed Web App', + hostname: 'app.example.com', +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateWebPlatform( + platformId = "", + name = "Renamed Web App", + hostname = "app.example.com" +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateWebPlatform( + "", // platformId + "Renamed Web App", // name + "app.example.com", // hostname + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateWebPlatform( + platformId: "", + name: "Renamed Web App", + hostname: "app.example.com" +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateWebPlatform( + "", + "Renamed Web App", + "app.example.com", + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_web_platform( + "", + "Renamed Web App", + "app.example.com", + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-web-platform \ + --platform-id \ + --name "Renamed Web App" \ + --hostname app.example.com +``` +{% /multicode %} + +# Delete a platform {% #delete-platform %} + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +await project.deletePlatform({ + platformId: '' +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +await project.deletePlatform({ + platformId: '' +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$project->deletePlatform( + platformId: '' +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +project.delete_platform( + platform_id = '' +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +project.delete_platform( + platform_id: '' +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +await project.DeletePlatform( + platformId: "" +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +await project.deletePlatform( + platformId: '', +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +project.deletePlatform( + platformId = "" +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.deletePlatform( + "", // platformId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +try await project.deletePlatform( + platformId: "" +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.DeletePlatform( + "", + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + project.delete_platform( + "", + ).await?; + + Ok(()) +} +``` +```bash +appwrite project delete-platform \ + --platform-id +``` +{% /multicode %} + +# Benefits {% #benefits %} + +- **Repeatable provisioning.** Script the full set of platforms a project needs and recreate it on demand, without clicking through the Console. +- **Environment parity.** Keep dev, staging, and production projects in sync by running the same script against each one. +- **CI and automation.** Add or rotate platforms from a CI job when a new preview environment spins up or a domain changes. diff --git a/src/routes/docs/platforms/project/policies/+page.markdoc b/src/routes/docs/platforms/project/policies/+page.markdoc new file mode 100644 index 00000000000..a00a96094e3 --- /dev/null +++ b/src/routes/docs/platforms/project/policies/+page.markdoc @@ -0,0 +1,2490 @@ +--- +layout: article +title: Policies +description: Configure password rules, session limits, user limits, and membership privacy on your Appwrite project programmatically using server SDKs. +--- + +Project policies control how users authenticate, how long their sessions live, how many users can sign up, and what team members can see about each other. Each policy is an independent toggle on the project. + +Policies can be configured from the Appwrite Console, or programmatically through any server SDK using the Project service. + +# Manage from the Console {% #manage-console %} + +{% only_dark %} +![Project policies in the Appwrite Console](/images/docs/project/dark/policies.avif) +{% /only_dark %} +{% only_light %} +![Project policies in the Appwrite Console](/images/docs/project/policies.avif) +{% /only_light %} + +To configure policies manually: + +1. Open your project in the Appwrite Console. +2. Navigate to **Auth** in the sidebar. +3. Open the **Security** tab. +4. Adjust the policy you want, then click **Update** on its card. + +# Available policies {% #available-policies %} + +| Policy ID | SDK method | Body | +| --- | --- | --- | +| `password-dictionary` | `updatePasswordDictionaryPolicy` | `enabled` | +| `password-history` | `updatePasswordHistoryPolicy` | `total` (1–`APP_LIMIT_COUNT`, or `null`) | +| `password-personal-data` | `updatePasswordPersonalDataPolicy` | `enabled` | +| `session-alert` | `updateSessionAlertPolicy` | `enabled` | +| `session-duration` | `updateSessionDurationPolicy` | `duration` (5–31536000 seconds) | +| `session-invalidation` | `updateSessionInvalidationPolicy` | `enabled` | +| `session-limit` | `updateSessionLimitPolicy` | `total` (1–`APP_LIMIT_COUNT`, or `null`) | +| `user-limit` | `updateUserLimitPolicy` | `total` (1–`APP_LIMIT_COUNT`, or `null`) | +| `membership-privacy` | `updateMembershipPrivacyPolicy` | `userId`, `userEmail`, `userPhone`, `userName`, `userMFA` (all bool, all optional) | + +{% info title="Required scopes" %} +The API key used for these calls needs `policies.read` to list or fetch policies, and `policies.write` to update them. +{% /info %} + +# List policies {% #list-policies %} + +List all policies configured for the project along with their current state. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.listPolicies({ + queries: [], + total: false +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.listPolicies({ + queries: [], + total: false +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->listPolicies( + queries: [], + total: false +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.list_policies( + queries = [], + total = False +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.list_policies( + queries: [], + total: false +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.ListPolicies( + queries: new List(), + total: false +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.listPolicies( + queries: [], + total: false, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.listPolicies( + queries = listOf(), + total = false +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.listPolicies( + List.of(), // queries + false, // total + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.listPolicies( + queries: [], + total: false +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" + "github.com/appwrite/sdk-for-go/project" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.ListPolicies( + project.WithListPoliciesQueries([]interface{}{}), + project.WithListPoliciesTotal(false), + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.list_policies( + Some(vec![]), + Some(false), + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project list-policies \ + --limit 25 +``` +{% /multicode %} + +# Get a policy {% #get-policy %} + +Fetch a single policy by its ID. The response fields depend on the policy type, matching the [Available policies](#available-policies) table above. + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectPolicyId } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.getPolicy({ + policyId: ProjectPolicyId.Passworddictionary +}); +``` +```server-deno +import { Client, Project, ProjectPolicyId } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.getPolicy({ + policyId: ProjectPolicyId.Passworddictionary +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->getPolicy( + policyId: ProjectPolicyId::PASSWORDDICTIONARY() +); +``` +```server-python +from appwrite.client import Client +from appwrite.enums import ProjectPolicyId +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.get_policy( + policy_id = ProjectPolicyId.PASSWORD_DICTIONARY +) +``` +```server-ruby +require 'appwrite' + +include Appwrite +include Appwrite::Enums + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.get_policy( + policy_id: ProjectPolicyId::PASSWORD_DICTIONARY +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.GetPolicy( + policyId: ProjectPolicyId.PasswordDictionary +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.getPolicy( + policyId: enums.ProjectPolicyId.passwordDictionary, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.enums.ProjectPolicyId +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.getPolicy( + policyId = ProjectPolicyId.PASSWORD_DICTIONARY +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.enums.ProjectPolicyId; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.getPolicy( + ProjectPolicyId.PASSWORD_DICTIONARY, // policyId + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.getPolicy( + policyId: .passwordDictionary +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.GetPolicy( + "password-dictionary", + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::enums::ProjectPolicyId; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.get_policy( + ProjectPolicyId::PasswordDictionary, + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project get-policy \ + --policy-id password-dictionary +``` +{% /multicode %} + +# Update password dictionary policy {% #update-password-dictionary-policy %} + +When enabled, new passwords are checked against a dictionary of common passwords and rejected if they match. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updatePasswordDictionaryPolicy({ + enabled: true +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updatePasswordDictionaryPolicy({ + enabled: true +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updatePasswordDictionaryPolicy( + enabled: true +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_password_dictionary_policy( + enabled = True +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_password_dictionary_policy( + enabled: true +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdatePasswordDictionaryPolicy( + enabled: true +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updatePasswordDictionaryPolicy( + enabled: true, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updatePasswordDictionaryPolicy( + enabled = true +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updatePasswordDictionaryPolicy( + true, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updatePasswordDictionaryPolicy( + enabled: true +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdatePasswordDictionaryPolicy(true) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_password_dictionary_policy(true).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-password-dictionary-policy \ + --enabled true +``` +{% /multicode %} + +# Update password history policy {% #update-password-history-policy %} + +Stores the last `total` password hashes per user and rejects new passwords that match. Pass `null` to disable. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updatePasswordHistoryPolicy({ + total: 5 +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updatePasswordHistoryPolicy({ + total: 5 +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updatePasswordHistoryPolicy( + total: 5 +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_password_history_policy( + total = 5 +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_password_history_policy( + total: 5 +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdatePasswordHistoryPolicy( + total: 5 +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updatePasswordHistoryPolicy( + total: 5, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updatePasswordHistoryPolicy( + total = 5 +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updatePasswordHistoryPolicy( + 5, // total + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updatePasswordHistoryPolicy( + total: 5 +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdatePasswordHistoryPolicy(5) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_password_history_policy(5).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-password-history-policy \ + --total 5 +``` +{% /multicode %} + +# Update password personal data policy {% #update-password-personal-data-policy %} + +When enabled, new passwords are rejected if they contain the user's ID, name, email, or phone number. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updatePasswordPersonalDataPolicy({ + enabled: true +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updatePasswordPersonalDataPolicy({ + enabled: true +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updatePasswordPersonalDataPolicy( + enabled: true +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_password_personal_data_policy( + enabled = True +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_password_personal_data_policy( + enabled: true +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdatePasswordPersonalDataPolicy( + enabled: true +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updatePasswordPersonalDataPolicy( + enabled: true, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updatePasswordPersonalDataPolicy( + enabled = true +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updatePasswordPersonalDataPolicy( + true, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updatePasswordPersonalDataPolicy( + enabled: true +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdatePasswordPersonalDataPolicy(true) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_password_personal_data_policy(true).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-password-personal-data-policy \ + --enabled true +``` +{% /multicode %} + +# Update session alert policy {% #update-session-alert-policy %} + +When enabled, the user receives an email each time a new session is created. The first session after sign-up does not trigger an alert. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateSessionAlertPolicy({ + enabled: true +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateSessionAlertPolicy({ + enabled: true +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateSessionAlertPolicy( + enabled: true +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_session_alert_policy( + enabled = True +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_session_alert_policy( + enabled: true +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateSessionAlertPolicy( + enabled: true +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateSessionAlertPolicy( + enabled: true, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateSessionAlertPolicy( + enabled = true +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateSessionAlertPolicy( + true, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateSessionAlertPolicy( + enabled: true +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateSessionAlertPolicy(true) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_session_alert_policy(true).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-session-alert-policy \ + --enabled true +``` +{% /multicode %} + +# Update session duration policy {% #update-session-duration-policy %} + +Sets the maximum lifetime of a session in seconds. Valid range is 5 seconds to 31536000 seconds (one year). + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateSessionDurationPolicy({ + duration: 86400 +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateSessionDurationPolicy({ + duration: 86400 +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateSessionDurationPolicy( + duration: 86400 +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_session_duration_policy( + duration = 86400 +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_session_duration_policy( + duration: 86400 +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateSessionDurationPolicy( + duration: 86400 +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateSessionDurationPolicy( + duration: 86400, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateSessionDurationPolicy( + duration = 86400 +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateSessionDurationPolicy( + 86400, // duration + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateSessionDurationPolicy( + duration: 86400 +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateSessionDurationPolicy(86400) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_session_duration_policy(86400).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-session-duration-policy \ + --duration 86400 +``` +{% /multicode %} + +# Update session invalidation policy {% #update-session-invalidation-policy %} + +When enabled, all existing sessions for a user are invalidated when their password is changed. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateSessionInvalidationPolicy({ + enabled: true +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateSessionInvalidationPolicy({ + enabled: true +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateSessionInvalidationPolicy( + enabled: true +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_session_invalidation_policy( + enabled = True +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_session_invalidation_policy( + enabled: true +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateSessionInvalidationPolicy( + enabled: true +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateSessionInvalidationPolicy( + enabled: true, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateSessionInvalidationPolicy( + enabled = true +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateSessionInvalidationPolicy( + true, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateSessionInvalidationPolicy( + enabled: true +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateSessionInvalidationPolicy(true) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_session_invalidation_policy(true).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-session-invalidation-policy \ + --enabled true +``` +{% /multicode %} + +# Update session limit policy {% #update-session-limit-policy %} + +Sets the maximum number of concurrent sessions allowed per user. When the limit is reached, the oldest session is dropped to make room for a new one. Pass `null` to remove the limit. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateSessionLimitPolicy({ + total: 10 +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateSessionLimitPolicy({ + total: 10 +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateSessionLimitPolicy( + total: 10 +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_session_limit_policy( + total = 10 +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_session_limit_policy( + total: 10 +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateSessionLimitPolicy( + total: 10 +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateSessionLimitPolicy( + total: 10, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateSessionLimitPolicy( + total = 10 +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateSessionLimitPolicy( + 10, // total + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateSessionLimitPolicy( + total: 10 +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateSessionLimitPolicy(10) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_session_limit_policy(10).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-session-limit-policy \ + --total 10 +``` +{% /multicode %} + +# Update user limit policy {% #update-user-limit-policy %} + +Sets the maximum number of users in the project. Existing users remain active when the limit is reached or exceeded; new sign-ups are rejected. Pass `null` to remove the limit. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateUserLimitPolicy({ + total: 1000 +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateUserLimitPolicy({ + total: 1000 +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateUserLimitPolicy( + total: 1000 +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_user_limit_policy( + total = 1000 +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_user_limit_policy( + total: 1000 +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateUserLimitPolicy( + total: 1000 +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateUserLimitPolicy( + total: 1000, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateUserLimitPolicy( + total = 1000 +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateUserLimitPolicy( + 1000, // total + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateUserLimitPolicy( + total: 1000 +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateUserLimitPolicy(1000) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_user_limit_policy(1000).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-user-limit-policy \ + --total 1000 +``` +{% /multicode %} + +# Update membership privacy policy {% #update-membership-privacy-policy %} + +Controls which fields of one team member's profile are visible to other members in the same team. Each field can be toggled independently. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateMembershipPrivacyPolicy({ + userId: true, + userEmail: false, + userPhone: false, + userName: true, + userMFA: false +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateMembershipPrivacyPolicy({ + userId: true, + userEmail: false, + userPhone: false, + userName: true, + userMFA: false +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateMembershipPrivacyPolicy( + userId: true, + userEmail: false, + userPhone: false, + userName: true, + userMFA: false +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_membership_privacy_policy( + user_id = True, + user_email = False, + user_phone = False, + user_name = True, + user_mfa = False +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_membership_privacy_policy( + user_id: true, + user_email: false, + user_phone: false, + user_name: true, + user_mfa: false +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateMembershipPrivacyPolicy( + userId: true, + userEmail: false, + userPhone: false, + userName: true, + userMFA: false +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateMembershipPrivacyPolicy( + userId: true, + userEmail: false, + userPhone: false, + userName: true, + userMFA: false, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateMembershipPrivacyPolicy( + userId = true, + userEmail = false, + userPhone = false, + userName = true, + userMFA = false +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateMembershipPrivacyPolicy( + true, // userId + false, // userEmail + false, // userPhone + true, // userName + false, // userMFA + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateMembershipPrivacyPolicy( + userId: true, + userEmail: false, + userPhone: false, + userName: true, + userMFA: false +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" + "github.com/appwrite/sdk-for-go/project" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateMembershipPrivacyPolicy( + project.WithUpdateMembershipPrivacyPolicyUserId(true), + project.WithUpdateMembershipPrivacyPolicyUserEmail(false), + project.WithUpdateMembershipPrivacyPolicyUserPhone(false), + project.WithUpdateMembershipPrivacyPolicyUserName(true), + project.WithUpdateMembershipPrivacyPolicyUserMFA(false), + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_membership_privacy_policy( + Some(true), + Some(false), + Some(false), + Some(true), + Some(false), + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-membership-privacy-policy \ + --user-id true \ + --user-email false \ + --user-phone false \ + --user-name true \ + --user-mfa false +``` +{% /multicode %} + +# Benefits {% #benefits %} + +- **Codify auth posture.** Keep password rules, session lifetimes, and user caps in version control alongside the rest of your project configuration. +- **Environment parity.** Apply the same policy script to dev, staging, and production projects to keep them aligned. +- **Faster incident response.** When a policy needs to change in a hurry (e.g. tightening session duration after a breach), update it from a script instead of clicking through the Console. diff --git a/src/routes/docs/platforms/project/protocols/+page.markdoc b/src/routes/docs/platforms/project/protocols/+page.markdoc new file mode 100644 index 00000000000..f3f95965503 --- /dev/null +++ b/src/routes/docs/platforms/project/protocols/+page.markdoc @@ -0,0 +1,285 @@ +--- +layout: article +title: Protocols +description: Enable or disable the REST, GraphQL, and WebSocket protocols on your Appwrite project programmatically using server SDKs. +--- + +Each Appwrite project exposes its API through three protocols: REST, GraphQL, and WebSocket. You can disable any protocol your clients don't use to shrink the project's surface area, then re-enable it when needed. + +Protocols can be toggled from the Appwrite Console, or programmatically through any server SDK using the Project service. + +# Manage from the Console {% #manage-console %} + +{% only_dark %} +![Project protocols in the Appwrite Console](/images/docs/project/dark/protocols.avif) +{% /only_dark %} +{% only_light %} +![Project protocols in the Appwrite Console](/images/docs/project/protocols.avif) +{% /only_light %} + +To toggle a protocol manually: + +1. Open your project in the Appwrite Console. +2. Open **Settings** from the bottom of the side nav. +3. Scroll to the **Protocols** card. +4. Flip the switch next to REST, GraphQL, or WebSocket. Use **Disable all** to turn off every protocol at once. + +# Available protocols {% #available-protocols %} + +| Protocol ID | Description | +| --- | --- | +| `rest` | Standard HTTP API requests from client SDKs. | +| `graphql` | GraphQL API access for queries and mutations. | +| `websocket` | Realtime subscriptions over WebSocket connections. | + +# Update a protocol {% #update-protocol %} + +The example below disables the REST protocol. Pass `enabled: true` to re-enable it. + +Disabling REST blocks client SDK traffic only. Server SDKs using an API key keep access, so you can always call this endpoint again to re-enable the protocol. + +{% info title="Required scope" %} +The API key used for this call needs the `project.write` scope. +{% /info %} + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectProtocolId } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateProtocol({ + protocolId: ProjectProtocolId.Rest, + enabled: false +}); +``` +```server-deno +import { Client, Project, ProjectProtocolId } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateProtocol({ + protocolId: ProjectProtocolId.Rest, + enabled: false +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateProtocol( + protocolId: ProjectProtocolId::REST(), + enabled: false +); +``` +```server-python +from appwrite.client import Client +from appwrite.enums import ProjectProtocolId +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_protocol( + protocol_id = ProjectProtocolId.REST, + enabled = False +) +``` +```server-ruby +require 'appwrite' + +include Appwrite +include Appwrite::Enums + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_protocol( + protocol_id: ProjectProtocolId::REST, + enabled: false +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateProtocol( + protocolId: ProjectProtocolId.Rest, + enabled: false +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateProtocol( + protocolId: enums.ProjectProtocolId.rest, + enabled: false, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.enums.ProjectProtocolId +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateProtocol( + protocolId = ProjectProtocolId.REST, + enabled = false +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.enums.ProjectProtocolId; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateProtocol( + ProjectProtocolId.REST, // protocolId + false, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateProtocol( + protocolId: .rest, + enabled: false +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateProtocol( + "rest", + false, + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::enums::ProjectProtocolId; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_protocol( + ProjectProtocolId::Rest, + false, + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-protocol \ + --protocol-id rest \ + --enabled false +``` +{% /multicode %} + +# Benefits {% #benefits %} + +- **Shrink the client surface area.** Disabled protocols are blocked for client SDK callers (anonymous, account session, JWT, and OAuth users). Server SDKs using an API key still have access, including to re-enable the protocol. +- **Repeatable provisioning.** Script the protocol set a project should expose and apply it from CI when spinning up a new environment. +- **Environment parity.** Keep dev, staging, and production in sync by running the same enable/disable script against each project. diff --git a/src/routes/docs/platforms/project/services/+page.markdoc b/src/routes/docs/platforms/project/services/+page.markdoc new file mode 100644 index 00000000000..ab193560040 --- /dev/null +++ b/src/routes/docs/platforms/project/services/+page.markdoc @@ -0,0 +1,296 @@ +--- +layout: article +title: Services +description: Enable or disable individual Appwrite services on your project programmatically using server SDKs. +--- + +Each Appwrite project ships with the full set of services enabled by default: Account, TablesDB, Storage, Functions, and so on. You can disable any service your clients don't use to remove it from the client-facing API. Disabled services remain accessible to server SDKs using an API key. + +Services can be toggled from the Appwrite Console, or programmatically through any server SDK using the Project service. + +# Manage from the Console {% #manage-console %} + +{% only_dark %} +![Project services in the Appwrite Console](/images/docs/project/dark/services.avif) +{% /only_dark %} +{% only_light %} +![Project services in the Appwrite Console](/images/docs/project/services.avif) +{% /only_light %} + +To toggle a service manually: + +1. Open your project in the Appwrite Console. +2. Open **Settings** from the bottom of the side nav. +3. Scroll to the **Services** card. +4. Flip the switch next to the service you want to enable or disable. Use **Disable all** to turn off every optional service at once. + +# Available services {% #available-services %} + +| Service ID | Description | +| --- | --- | +| `account` | User accounts and authentication. | +| `avatars` | App image, icon, and avatar helpers. | +| `tablesdb` | TablesDB tables, columns, and rows. | +| `locale` | Locale and geographic helpers. | +| `health` | Health checks and status. | +| `project` | Project configuration. | +| `storage` | File storage buckets and files. | +| `teams` | Teams and shared resource access. | +| `users` | User administration via server SDKs. | +| `sites` | Sites hosting and deployments. | +| `functions` | Cloud Functions. | +| `proxy` | Custom domain proxy. | +| `graphql` | GraphQL endpoint. | +| `migrations` | Third-party data migrations. | +| `messaging` | Push, SMS, and email messaging. | +| `databases` | Legacy Databases collections and documents. | + +# Update a service {% #update-service %} + +The example below disables the Account service. Pass `enabled: true` to re-enable it. + +{% info title="Required scope" %} +The API key used for this call needs the `project.write` scope. +{% /info %} + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectServiceId } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateService({ + serviceId: ProjectServiceId.Account, + enabled: false +}); +``` +```server-deno +import { Client, Project, ProjectServiceId } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +const project = new Project(client); + +const result = await project.updateService({ + serviceId: ProjectServiceId.Account, + enabled: false +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$project = new Project($client); + +$result = $project->updateService( + serviceId: ProjectServiceId::ACCOUNT(), + enabled: false +); +``` +```server-python +from appwrite.client import Client +from appwrite.enums import ProjectServiceId +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') +client.set_project('') +client.set_key('') + +project = Project(client) + +result = project.update_service( + service_id = ProjectServiceId.ACCOUNT, + enabled = False +) +``` +```server-ruby +require 'appwrite' + +include Appwrite +include Appwrite::Enums + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +project = Project.new(client) + +response = project.update_service( + service_id: ProjectServiceId::ACCOUNT, + enabled: false +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +Project project = new Project(client); + +var result = await project.UpdateService( + serviceId: ProjectServiceId.Account, + enabled: false +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); + +Project project = Project(client); + +final result = await project.updateService( + serviceId: enums.ProjectServiceId.account, + enabled: false, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.enums.ProjectServiceId +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +val project = Project(client) + +val response = project.updateService( + serviceId = ProjectServiceId.ACCOUNT, + enabled = false +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.enums.ProjectServiceId; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +Project project = new Project(client); + +project.updateService( + ProjectServiceId.ACCOUNT, // serviceId + false, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey("") + +let project = Project(client) + +let result = try await project.updateService( + serviceId: .account, + enabled: false +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + service := appwrite.NewProject(client) + result, err := service.UpdateService( + "account", + false, + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::enums::ProjectServiceId; +use appwrite::services::project::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new() + .set_endpoint("https://.cloud.appwrite.io/v1") + .set_project("") + .set_key(""); + + let project = Project::new(&client); + + let result = project.update_service( + ProjectServiceId::Account, + false, + ).await?; + + println!("{:?}", result); + Ok(()) +} +``` +```bash +appwrite project update-service \ + --service-id account \ + --enabled false +``` +{% /multicode %} + +# Benefits {% #benefits %} + +- **Shrink the client surface area.** Disable services your client apps don't use so they're no longer callable from client SDKs. +- **Server-only access.** Disabled services stay reachable from server SDKs using an API key, useful when you want a service available to your backend but hidden from clients. +- **Repeatable provisioning.** Script the service set a project should expose and apply it from CI when spinning up a new environment. diff --git a/src/routes/docs/platforms/project/smtp/+page.markdoc b/src/routes/docs/platforms/project/smtp/+page.markdoc new file mode 100644 index 00000000000..6b60849d929 --- /dev/null +++ b/src/routes/docs/platforms/project/smtp/+page.markdoc @@ -0,0 +1,605 @@ +--- +layout: article +title: SMTP +description: Configure a custom SMTP server to send Appwrite's account management emails from your own domain, improve deliverability, and unlock custom email templates. +--- + +By default, Appwrite sends account management emails such as verification, password recovery, and magic URL links from a shared SMTP server. Configuring a custom SMTP server lets you send these emails through your own provider instead. This sends mail from your own domain, improves deliverability, and unlocks [custom email templates](/docs/platforms/project/email-templates). + +# Configure in the Console {% #console %} + +{% only_dark %} +![SMTP settings in the Appwrite Console](/images/docs/project/dark/smtp.avif) +{% /only_dark %} +{% only_light %} +![SMTP settings in the Appwrite Console](/images/docs/project/smtp.avif) +{% /only_light %} + +To configure a custom SMTP server from the Appwrite Console: + +1. Navigate to your project. +2. Open the **Settings** section and select the **SMTP** tab. +3. Enable **Custom SMTP server**. +4. Enter your provider's **Sender name**, **Sender email**, **Server host**, and **Server port**. Add a **Username** and **Password** if your provider requires authentication, set a **Reply to** address if needed, and choose the encryption protocol (TLS or SSL). +5. Click **Update**. Appwrite validates the connection to your SMTP server before saving, so the credentials must be correct. + +# Configure with a Server SDK {% #server-sdks %} + +You can also manage SMTP programmatically using a [Server SDK](/docs/sdks#server). + +{% info title="Required scope" %} +The API key used for these calls needs the `project.write` scope. +{% /info %} + +## Configure SMTP {% #configure-smtp %} + +Every field is optional, so you can change only the values you need. Any field you omit keeps its current value. To enable SMTP, the project must have a `host`, `port`, and `senderEmail` set, either in this call or from a previous one. When you enable SMTP, Appwrite validates the connection to your server before saving. The encryption protocol accepts `tls` or `ssl`. + +{% multicode %} +```server-nodejs +import { Client, Project, ProjectSMTPSecure } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.updateSMTP({ + host: 'smtp.example.com', + port: 587, + username: '', // optional + password: '', // optional + senderEmail: 'email@example.com', + senderName: '', // optional + replyToEmail: 'email@example.com', // optional + replyToName: '', // optional + secure: ProjectSMTPSecure.Tls, // optional + enabled: true +}); +``` +```server-deno +import { Client, Project, ProjectSMTPSecure } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.updateSMTP({ + host: 'smtp.example.com', + port: 587, + username: '', // optional + password: '', // optional + senderEmail: 'email@example.com', + senderName: '', // optional + replyToEmail: 'email@example.com', // optional + replyToName: '', // optional + secure: ProjectSMTPSecure.Tls, // optional + enabled: true +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your API key + +$project = new Project($client); + +$result = $project->updateSMTP( + host: 'smtp.example.com', + port: 587, + username: '', // optional + password: '', // optional + senderEmail: 'email@example.com', + senderName: '', // optional + replyToEmail: 'email@example.com', // optional + replyToName: '', // optional + secure: ProjectSMTPSecure::TLS(), // optional + enabled: true +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project +from appwrite.models import Project as ProjectModel +from appwrite.enums import ProjectSMTPSecure + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your API key + +project = Project(client) + +result: ProjectModel = project.update_smtp( + host = 'smtp.example.com', + port = 587, + username = '', # optional + password = '', # optional + sender_email = 'email@example.com', + sender_name = '', # optional + reply_to_email = 'email@example.com', # optional + reply_to_name = '', # optional + secure = ProjectSMTPSecure.TLS, # optional + enabled = True +) + +print(result.model_dump()) +``` +```server-ruby +require 'appwrite' + +include Appwrite +include Appwrite::Enums + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your API key + +project = Project.new(client) + +result = project.update_smtp( + host: 'smtp.example.com', + port: 587, + username: '', # optional + password: '', # optional + sender_email: 'email@example.com', + sender_name: '', # optional + reply_to_email: 'email@example.com', # optional + reply_to_name: '', # optional + secure: ProjectSMTPSecure::TLS, # optional + enabled: true +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Enums; +using Appwrite.Models; +using Appwrite.Services; + +Client client = new Client() + .SetEndPoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .SetProject("") // Your project ID + .SetKey(""); // Your API key + +Project project = new Project(client); + +Project result = await project.UpdateSMTP( + host: "smtp.example.com", + port: 587, + username: "", // optional + password: "", // optional + senderEmail: "email@example.com", + senderName: "", // optional + replyToEmail: "email@example.com", // optional + replyToName: "", // optional + secure: ProjectSMTPSecure.Tls, // optional + enabled: true +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; +import 'package:dart_appwrite/enums.dart' as enums; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +Project project = Project(client); + +Project result = await project.updateSMTP( + host: 'smtp.example.com', + port: 587, + username: '', // (optional) + password: '', // (optional) + senderEmail: 'email@example.com', + senderName: '', // (optional) + replyToEmail: 'email@example.com', // (optional) + replyToName: '', // (optional) + secure: enums.ProjectSMTPSecure.tls, // (optional) + enabled: true, +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.enums.ProjectSMTPSecure +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +val project = Project(client) + +val response = project.updateSMTP( + host = "smtp.example.com", + port = 587, + username = "", // optional + password = "", // optional + senderEmail = "email@example.com", + senderName = "", // optional + replyToEmail = "email@example.com", // optional + replyToName = "", // optional + secure = ProjectSMTPSecure.TLS, // optional + enabled = true +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.enums.ProjectSMTPSecure; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your API key + +Project project = new Project(client); + +project.updateSMTP( + "smtp.example.com", // host + 587, // port + "", // username (optional) + "", // password (optional) + "email@example.com", // senderEmail + "", // senderName (optional) + "email@example.com", // replyToEmail (optional) + "", // replyToName (optional) + ProjectSMTPSecure.TLS, // secure (optional) + true, // enabled + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite +import AppwriteEnums + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +let project = Project(client) + +let result = try await project.updateSMTP( + host: "smtp.example.com", + port: 587, + username: "", // optional + password: "", // optional + senderEmail: "email@example.com", + senderName: "", // optional + replyToEmail: "email@example.com", // optional + replyToName: "", // optional + secure: .tls, // optional + enabled: true +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + result, err := project.UpdateSMTP( + appwrite.WithUpdateSMTPHost("smtp.example.com"), + appwrite.WithUpdateSMTPPort(587), + appwrite.WithUpdateSMTPUsername(""), + appwrite.WithUpdateSMTPPassword(""), + appwrite.WithUpdateSMTPSenderEmail("email@example.com"), + appwrite.WithUpdateSMTPSenderName(""), + appwrite.WithUpdateSMTPReplyToEmail("email@example.com"), + appwrite.WithUpdateSMTPReplyToName(""), + appwrite.WithUpdateSMTPSecure("tls"), + appwrite.WithUpdateSMTPEnabled(true), + ) + + if err != nil { + panic(err) + } + + fmt.Println(result) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; +use appwrite::enums::ProjectSMTPSecure; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new(); + client.set_endpoint("https://.cloud.appwrite.io/v1"); // Your API Endpoint + client.set_project(""); // Your project ID + client.set_key(""); // Your API key + + let project = Project::new(&client); + + let result = project.update_smtp( + Some("smtp.example.com"), + Some(587), + Some(""), // optional + Some(""), // optional + Some("email@example.com"), + Some(""), // optional + Some("email@example.com"), // optional + Some(""), // optional + Some(ProjectSMTPSecure::Tls), // optional + Some(true) + ).await?; + + let _ = result; + + Ok(()) +} +``` +```bash +appwrite project update-smtp \ + --host smtp.example.com \ + --port 587 \ + --username "" \ + --password "" \ + --sender-email email@example.com \ + --sender-name "" \ + --reply-to-email email@example.com \ + --reply-to-name "" \ + --secure tls \ + --enabled true +``` +{% /multicode %} + +## Send a test email {% #send-test-email %} + +Once SMTP is configured, send a test email to confirm that your server delivers mail. Appwrite sends a sample email to each address you provide, up to a maximum of 10 recipients. + +{% multicode %} +```server-nodejs +import { Client, Project } from 'node-appwrite'; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.createSMTPTest({ + emails: ['email@example.com'] +}); +``` +```server-deno +import { Client, Project } from "npm:node-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +const project = new Project(client); + +const result = await project.createSMTPTest({ + emails: ['email@example.com'] +}); +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + ->setProject('') // Your project ID + ->setKey(''); // Your API key + +$project = new Project($client); + +$result = $project->createSMTPTest( + emails: ['email@example.com'] +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.project import Project + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your API key + +project = Project(client) + +result = project.create_smtp_test( + emails = ['email@example.com'] +) +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new + .set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint + .set_project('') # Your project ID + .set_key('') # Your API key + +project = Project.new(client) + +result = project.create_smtp_test( + emails: ['email@example.com'] +) +``` +```server-dotnet +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 + .SetKey(""); // Your API key + +Project project = new Project(client); + +await project.CreateSMTPTest( + emails: new List { "email@example.com" } +); +``` +```server-dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('') // Your project ID + .setKey(''); // Your API key + +Project project = Project(client); + +await project.createSMTPTest( + emails: ['email@example.com'], +); +``` +```server-kotlin +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Project + +val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +val project = Project(client) + +val response = project.createSMTPTest( + emails = listOf("email@example.com") +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Project; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey(""); // Your API key + +Project project = new Project(client); + +project.createSMTPTest( + List.of("email@example.com"), // emails + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) +); +``` +```server-swift +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("") // Your project ID + .setKey("") // Your API key + +let project = Project(client) + +let result = try await project.createSMTPTest( + emails: ["email@example.com"] +) +``` +```server-go +package main + +import ( + "fmt" + "github.com/appwrite/sdk-for-go/appwrite" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + project := appwrite.NewProject(client) + response, err := project.CreateSMTPTest( + []interface{}{"email@example.com"}, + ) + + if err != nil { + panic(err) + } + + fmt.Println(response) +} +``` +```server-rust +use appwrite::Client; +use appwrite::services::Project; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = Client::new(); + client.set_endpoint("https://.cloud.appwrite.io/v1"); // Your API Endpoint + client.set_project(""); // Your project ID + client.set_key(""); // Your API key + + let project = Project::new(&client); + + project.create_smtp_test( + vec!["email@example.com"] + ).await?; + + Ok(()) +} +``` +```bash +appwrite project create-smtp-test \ + --emails email@example.com +``` +{% /multicode %} + +# Benefits {% #benefits %} + +- **Send from your own domain.** Deliver account emails from your branded sender address instead of Appwrite's shared one, so users recognize and trust them. +- **Better deliverability.** Routing mail through an authenticated provider, with SPF and DKIM set up on your domain, reduces the chance of verification and recovery emails landing in spam. +- **Unlocks custom templates.** A custom SMTP server is required to customize [email templates](/docs/platforms/project/email-templates) per locale. diff --git a/static/images/docs/project/auth-methods.avif b/static/images/docs/project/auth-methods.avif new file mode 100644 index 00000000000..96c2e0c318a Binary files /dev/null and b/static/images/docs/project/auth-methods.avif differ diff --git a/static/images/docs/platform/create-api-key.avif b/static/images/docs/project/create-api-key.avif similarity index 100% rename from static/images/docs/platform/create-api-key.avif rename to static/images/docs/project/create-api-key.avif diff --git a/static/images/docs/project/dark/auth-methods.avif b/static/images/docs/project/dark/auth-methods.avif new file mode 100644 index 00000000000..51797f206ff Binary files /dev/null and b/static/images/docs/project/dark/auth-methods.avif differ diff --git a/static/images/docs/platform/dark/create-api-key.avif b/static/images/docs/project/dark/create-api-key.avif similarity index 100% rename from static/images/docs/platform/dark/create-api-key.avif rename to static/images/docs/project/dark/create-api-key.avif diff --git a/static/images/docs/project/dark/email-templates.avif b/static/images/docs/project/dark/email-templates.avif new file mode 100644 index 00000000000..9f399869417 Binary files /dev/null and b/static/images/docs/project/dark/email-templates.avif differ diff --git a/static/images/docs/project/dark/labels.avif b/static/images/docs/project/dark/labels.avif new file mode 100644 index 00000000000..0ce8f06595a Binary files /dev/null and b/static/images/docs/project/dark/labels.avif differ diff --git a/static/images/docs/project/dark/mock-phones.avif b/static/images/docs/project/dark/mock-phones.avif new file mode 100644 index 00000000000..0c775352c16 Binary files /dev/null and b/static/images/docs/project/dark/mock-phones.avif differ diff --git a/static/images/docs/project/dark/oauth-providers.avif b/static/images/docs/project/dark/oauth-providers.avif new file mode 100644 index 00000000000..e4c031cc471 Binary files /dev/null and b/static/images/docs/project/dark/oauth-providers.avif differ diff --git a/static/images/docs/project/dark/platforms.avif b/static/images/docs/project/dark/platforms.avif new file mode 100644 index 00000000000..08b105f48a8 Binary files /dev/null and b/static/images/docs/project/dark/platforms.avif differ diff --git a/static/images/docs/project/dark/policies.avif b/static/images/docs/project/dark/policies.avif new file mode 100644 index 00000000000..6cea4b15c2c Binary files /dev/null and b/static/images/docs/project/dark/policies.avif differ diff --git a/static/images/docs/project/dark/protocols.avif b/static/images/docs/project/dark/protocols.avif new file mode 100644 index 00000000000..8c0a67eb35f Binary files /dev/null and b/static/images/docs/project/dark/protocols.avif differ diff --git a/static/images/docs/project/dark/services.avif b/static/images/docs/project/dark/services.avif new file mode 100644 index 00000000000..397eea4d613 Binary files /dev/null and b/static/images/docs/project/dark/services.avif differ diff --git a/static/images/docs/project/dark/smtp.avif b/static/images/docs/project/dark/smtp.avif new file mode 100644 index 00000000000..72641e8a88e Binary files /dev/null and b/static/images/docs/project/dark/smtp.avif differ diff --git a/static/images/docs/project/email-templates.avif b/static/images/docs/project/email-templates.avif new file mode 100644 index 00000000000..90dddabd537 Binary files /dev/null and b/static/images/docs/project/email-templates.avif differ diff --git a/static/images/docs/project/labels.avif b/static/images/docs/project/labels.avif new file mode 100644 index 00000000000..65269cec052 Binary files /dev/null and b/static/images/docs/project/labels.avif differ diff --git a/static/images/docs/project/mock-phones.avif b/static/images/docs/project/mock-phones.avif new file mode 100644 index 00000000000..25e59b1b896 Binary files /dev/null and b/static/images/docs/project/mock-phones.avif differ diff --git a/static/images/docs/project/oauth-providers.avif b/static/images/docs/project/oauth-providers.avif new file mode 100644 index 00000000000..52c778c5f47 Binary files /dev/null and b/static/images/docs/project/oauth-providers.avif differ diff --git a/static/images/docs/project/platforms.avif b/static/images/docs/project/platforms.avif new file mode 100644 index 00000000000..8b521972193 Binary files /dev/null and b/static/images/docs/project/platforms.avif differ diff --git a/static/images/docs/project/policies.avif b/static/images/docs/project/policies.avif new file mode 100644 index 00000000000..55ec91fcdbf Binary files /dev/null and b/static/images/docs/project/policies.avif differ diff --git a/static/images/docs/project/protocols.avif b/static/images/docs/project/protocols.avif new file mode 100644 index 00000000000..27656745a6b Binary files /dev/null and b/static/images/docs/project/protocols.avif differ diff --git a/static/images/docs/project/services.avif b/static/images/docs/project/services.avif new file mode 100644 index 00000000000..eaa3aa8aa02 Binary files /dev/null and b/static/images/docs/project/services.avif differ diff --git a/static/images/docs/project/smtp.avif b/static/images/docs/project/smtp.avif new file mode 100644 index 00000000000..eb1d1a6059a Binary files /dev/null and b/static/images/docs/project/smtp.avif differ