diff --git a/src/routes/docs/Sidebar.svelte b/src/routes/docs/Sidebar.svelte
index fbee7c5cad..f0abe5776b 100644
--- a/src/routes/docs/Sidebar.svelte
+++ b/src/routes/docs/Sidebar.svelte
@@ -107,7 +107,8 @@
{
label: 'Realtime',
href: '/docs/apis/realtime',
- icon: 'icon-clock'
+ icon: 'icon-clock',
+ isParent: true
},
{
label: 'REST',
diff --git a/src/routes/docs/apis/+layout.svelte b/src/routes/docs/apis/graphql/+layout.svelte
similarity index 75%
rename from src/routes/docs/apis/+layout.svelte
rename to src/routes/docs/apis/graphql/+layout.svelte
index 2416c16742..93e22c8ceb 100644
--- a/src/routes/docs/apis/+layout.svelte
+++ b/src/routes/docs/apis/graphql/+layout.svelte
@@ -1,6 +1,6 @@
diff --git a/src/routes/docs/apis/realtime/+layout.svelte b/src/routes/docs/apis/realtime/+layout.svelte
new file mode 100644
index 0000000000..80ebef8218
--- /dev/null
+++ b/src/routes/docs/apis/realtime/+layout.svelte
@@ -0,0 +1,64 @@
+
+
+
+
+
+
diff --git a/src/routes/docs/apis/realtime/+page.markdoc b/src/routes/docs/apis/realtime/+page.markdoc
index 748e9fa820..3132a0c990 100644
--- a/src/routes/docs/apis/realtime/+page.markdoc
+++ b/src/routes/docs/apis/realtime/+page.markdoc
@@ -4,7 +4,7 @@ title: Realtime
description: Want to build dynamic and interactive applications with real-time data updates? Appwrite Realtime API makes it possible, get started with our intro guide.
---
-Appwrite supports multiple protocols for accessing the server, including [REST](/docs/apis/rest), [GraphQL](/docs/apis/graphql), and [Realtime](/docs/apis/realtime). The Appwrite Realtime allows you to listen to any Appwrite events in realtime using the `Realtime` service.
+Appwrite supports multiple protocols for accessing the server, including [REST](/docs/apis/rest), [GraphQL](/docs/apis/graphql), and Realtime. The Appwrite Realtime allows you to listen to any Appwrite events in realtime using the `Realtime` service.
Instead of requesting new data via HTTP, the subscription will receive new data every time it changes, any connected client receives that update within milliseconds via a WebSocket connection.
@@ -90,744 +90,14 @@ val subscription = realtime.subscribe(Channel.files()) {
{% /multicode %}
-To subscribe to updates from different Appwrite resources, you need to specify one or more [channels](/docs/apis/realtime#channels). The channels offer a wide and powerful selection that will allow you to listen to all possible resources. This allows you to receive updates not only from the database, but from _all_ the services that Appwrite offers.
+To subscribe to updates from different Appwrite resources, you need to specify one or more [channels](/docs/apis/realtime/channels). The channels offer a wide and powerful selection that will allow you to listen to all possible resources. This allows you to receive updates not only from the database, but from _all_ the services that Appwrite offers.
If you subscribe to a channel, you will receive callbacks for a variety of events related to the channel. The events column in the callback can be used to filter and respond to specific events in a channel.
[View a list of all available events](/docs/advanced/platform/events).
-# Channel helpers {% #channel-helpers %}
-
-Instead of manually writing channel strings, you can use the `Channel` helper class to build type-safe channel subscriptions. The helper provides a fluent API that makes it easier to construct channel strings and reduces errors.
-
-{% multicode %}
-```client-web
-import { Client, Realtime, Channel } from "appwrite";
-
-const client = new Client()
- .setEndpoint('https://.cloud.appwrite.io/v1')
- .setProject('');
-
-const realtime = new Realtime(client);
-
-// Subscribe to account channel
-const subscription = await realtime.subscribe(Channel.account(), response => {
- console.log(response);
-});
-
-// Subscribe to a specific row
-const rowSubscription = await realtime.subscribe(
- Channel.tablesdb('').table('').row(''),
- response => {
- console.log(response);
- }
-);
-```
-
-```client-flutter
-import 'package:appwrite/appwrite.dart';
-
-final client = Client()
- .setEndpoint('https://.cloud.appwrite.io/v1')
- .setProject('');
-
-final realtime = Realtime(client);
-
-// Subscribe to account channel
-final subscription = realtime.subscribe([Channel.account()]);
-
-// Subscribe to a specific row
-final docSubscription = realtime.subscribe([
- Channel.tablesdb('').table('').row('')
-]);
-```
-
-```client-apple
-import Appwrite
-
-let client = Client()
- .setEndpoint("https://.cloud.appwrite.io/v1")
- .setProject("")
-
-let realtime = Realtime(client)
-
-// Subscribe to account channel
-let subscription = realtime.subscribe(channels: [Channel.account()]) { response in
- print(String(describing: response))
-}
-
-// Subscribe to a specific row
-let docSubscription = realtime.subscribe(
- channels: [Channel.tablesdb("").table("").row("")]
-) { response in
- print(String(describing: response))
-}
-```
-
-```client-android-kotlin
-import io.appwrite.Client
-import io.appwrite.services.Realtime
-import io.appwrite.extensions.Channel
-
-val client = Client(context)
- .setEndpoint("https://.cloud.appwrite.io/v1")
- .setProject("")
-
-val realtime = Realtime(client)
-
-// Subscribe to account channel
-val subscription = realtime.subscribe(Channel.account()) {
- print(it.toString())
-}
-
-// Subscribe to a specific row
-val docSubscription = realtime.subscribe(
- Channel.tablesdb("").table("").row("")
-) {
- print(it.toString())
-}
-```
-
-{% /multicode %}
-
-The `Channel` helper supports all available channels and allows you to:
-- Build channels with a fluent, chainable API
-- Optionally specify resource IDs (omit IDs to subscribe to all resources)
-- Add event filters like `.create()`, `.update()`, or `.delete()`
-
{% info title="Permissions" %}
All subscriptions are secured by the [permissions system](/docs/advanced/platform/permissions) offered by Appwrite, meaning a user will only receive updates to resources they have permission to access.
Using `Role.any()` on read permissions will allow any client to receive updates.
{% /info %}
-
-# Authentication {% #authentication %}
-
-Realtime authenticates using an existing user session. If you authenticate **after** creating a subscription, the subscription will not receive updates for the newly authenticated user. You will need to re-create the subscription to work with the new user.
-
-More information and examples of authenticating users can be found in the dedicated [authentication docs](/docs/products/auth).
-
-# Examples {% #examples %}
-The examples below will show you how you can use Realtime in various ways.
-
-## Subscribe to a Channel {% #subscribe-to-a-channel %}
-In this example we are subscribing to all updates related to our account by using the `account` channel. This will be triggered by any update related to the authenticated user, like updating the user's name or e-mail address.
-
-{% multicode %}
-```client-web
-import { Client, Realtime, Channel } from "appwrite";
-
-const client = new Client()
- .setEndpoint('https://.cloud.appwrite.io/v1')
- .setProject('');
-
-const realtime = new Realtime(client);
-
-const subscription = await realtime.subscribe(Channel.account(), response => {
- // Callback will be executed on all account events.
- console.log(response);
-});
-```
-
-```client-flutter
-import 'package:appwrite/appwrite.dart';
-
-final client = Client()
- .setEndpoint('https://.cloud.appwrite.io/v1')
- .setProject('');
-
-final realtime = Realtime(client);
-
-final subscription = realtime.subscribe([Channel.account()]);
-
-subscription.stream.listen((response) {
- // Callback will be executed on all account events.
- print(response);
-})
-```
-
-```client-apple
-import Appwrite
-import AppwriteModels
-
-let client = Client()
- .setEndpoint("https://.cloud.appwrite.io/v1")
- .setProject("")
-
-let realtime = Realtime(client)
-
-let subscription = realtime.subscribe(channels: [Channel.account()]) { response in
- // Callback will be executed on all account events.
- print(String(describing: response))
-}
-```
-
-```client-android-kotlin
-import io.appwrite.Client
-import io.appwrite.services.Realtime
-import io.appwrite.extensions.Channel
-
-val client = Client(context)
- .setEndpoint("https://.cloud.appwrite.io/v1")
- .setProject("")
-
-val realtime = Realtime(client)
-
-val subscription = realtime.subscribe(Channel.account()) {
- // Callback will be executed on all account events.
- print(it.payload.toString())
-}
-```
-
-{% /multicode %}
-
-## Subscribe to Multiple Channels {% #subscribe-to-multiple-channel %}
-
-You can also listen to multiple channels at once by passing an array of channels. This will trigger the callback for any events for all channels passed.
-
-In this example we are listening to a specific row and all files by subscribing to `Channel.tablesdb("").table("").row("")` and `Channel.files()` channels.
-
-{% multicode %}
-```client-web
-import { Client, Realtime, Channel } from "appwrite";
-
-const client = new Client()
- .setEndpoint('https://.cloud.appwrite.io/v1')
- .setProject('');
-
-const realtime = new Realtime(client);
-
-const subscription = await realtime.subscribe([
- Channel.tablesdb('').table('').row(''),
- Channel.files()
-], response => {
- // Callback will be executed on changes for the row and all files.
- console.log(response);
-});
-```
-
-```client-flutter
-import 'package:appwrite/appwrite.dart';
-
-final client = Client()
- .setEndpoint('https://.cloud.appwrite.io/v1')
- .setProject('');
-
-final realtime = Realtime(client);
-
-final subscription = realtime.subscribe([
- Channel.tablesdb('').table('').row(''),
- Channel.files()
-]);
-
-subscription.stream.listen((response) {
- // Callback will be executed on changes for the row and all files.
- print(response);
-})
-```
-
-```client-apple
-import Appwrite
-import AppwriteModels
-
-let client = Client()
- .setEndpoint("https://.cloud.appwrite.io/v1")
- .setProject("")
-
-let realtime = Realtime(client)
-
-realtime.subscribe(channels: [
- Channel.tablesdb("").table("").row(""),
- Channel.files()
-]) { response in
- // Callback will be executed on changes for the row and all files.
- print(String(describing: response))
-}
-```
-
-```client-android-kotlin
-import io.appwrite.Client
-import io.appwrite.services.Realtime
-import io.appwrite.extensions.Channel
-
-val client = Client(context)
- .setEndpoint("https://.cloud.appwrite.io/v1")
- .setProject("")
-val realtime = Realtime(client)
-
-realtime.subscribe(
- Channel.tablesdb("").table("").row(""),
- Channel.files()
-) {
- // Callback will be executed on changes for the row and all files.
- print(it.toString())
-}
-```
-
-{% /multicode %}
-
-## Unsubscribe {% #unsubscribe %}
-
-If you no longer want to receive updates from a subscription, you can unsubscribe so that your callbacks are no longer called. Leaving old subscriptions alive and resubscribing can result in duplicate subscriptions and cause race conditions.
-
-{% multicode %}
-```client-web
-import { Client, Realtime, Channel } from "appwrite";
-
-const client = new Client()
- .setEndpoint('https://.cloud.appwrite.io/v1')
- .setProject('');
-
-const realtime = new Realtime(client);
-
-const subscription = await realtime.subscribe(Channel.files(), response => {
- // Callback will be executed on changes for all files.
- console.log(response);
-});
-
-// Closes the subscription.
-await subscription.close();
-```
-
-```client-flutter
-import 'package:appwrite/appwrite.dart';
-
-final client = Client()
- .setEndpoint('https://.cloud.appwrite.io/v1')
- .setProject('');
-
-final realtime = Realtime(client);
-
-final subscription = realtime.subscribe([Channel.files()]);
-
-subscription.stream.listen((response) {
- // Callback will be executed on changes for all files.
- print(response);
-})
-
-// Closes the subscription.
-subscription.close();
-```
-
-```client-apple
-import Appwrite
-
-let client = Client()
-let realtime = Realtime(client)
-
-let subscription = realtime.subscribe(channels: [Channel.files()]) { response in
- // Callback will be executed on changes for all files.
- print(response.toString())
-}
-
-// Closes the subscription.
-subscription.close()
-```
-
-```client-android-kotlin
-import io.appwrite.Client
-import io.appwrite.services.Realtime
-import io.appwrite.extensions.Channel
-
-val client = Client(context)
- .setEndpoint("https://.cloud.appwrite.io/v1")
- .setProject("")
-
-val realtime = Realtime(client)
-
-val subscription = realtime.subscribe(Channel.files()) {
- // Callback will be executed on changes for all files.
- print(it.toString())
-}
-
-// Closes the subscription.
-subscription.close()
-```
-
-{% /multicode %}
-
-# Queries {% #queries %}
-
-You can filter realtime events by passing queries as a third parameter when subscribing. Events are filtered server-side based on your queries, so your callback only receives updates that match your conditions. This allows you to use familiar SDK queries like `Query.equal` to automatically filter events instead of filtering manually in your callback.
-
-{% multicode %}
-```client-web
-import { Client, Realtime, Channel, Query } from "appwrite";
-
-const client = new Client()
- .setEndpoint('https://.cloud.appwrite.io/v1')
- .setProject('');
-
-const realtime = new Realtime(client);
-
-// Subscribe to all updates
-const allVotes = await realtime.subscribe(
- Channel.tablesdb('').table('').row(),
- response => {
- console.log(response.payload);
- }
-);
-
-// Subscribe to updates where person equals 'person1'
-const person1Votes = await realtime.subscribe(
- Channel.tablesdb('').table('').row(),
- response => {
- console.log(response.payload);
- },
- [Query.equal('person', ['person1'])]
-);
-
-// Subscribe to updates where person is not 'person1'
-const otherVotes = await realtime.subscribe(
- Channel.tablesdb('').table('').row(),
- response => {
- console.log(response.payload);
- },
- [Query.notEqual('person', 'person1')]
-);
-```
-
-```client-flutter
-import 'package:appwrite/appwrite.dart';
-
-final client = Client()
- .setEndpoint('https://.cloud.appwrite.io/v1')
- .setProject('');
-
-final realtime = Realtime(client);
-
-// Subscribe to all updates
-final allVotes = realtime.subscribe(
- [Channel.tablesdb('').table('').row()]
-);
-
-allVotes.stream.listen((response) {
- print(response.payload);
-});
-
-// Subscribe to updates where person equals 'person1'
-final person1Votes = realtime.subscribe(
- [Channel.tablesdb('').table('').row()],
- queries: [Query.equal('person', ['person1'])]
-);
-
-person1Votes.stream.listen((response) {
- print(response.payload);
-});
-
-// Subscribe to updates where person is not 'person1'
-final otherVotes = realtime.subscribe(
- [Channel.tablesdb('').table('').row()],
- queries: [Query.notEqual('person', 'person1')]
-);
-
-otherVotes.stream.listen((response) {
- print(response.payload);
-});
-```
-
-```client-apple
-import Appwrite
-import AppwriteModels
-
-let client = Client()
- .setEndpoint("https://.cloud.appwrite.io/v1")
- .setProject("")
-
-let realtime = Realtime(client)
-
-// Subscribe to all updates
-let allVotes = realtime.subscribe(
- channels: [Channel.tablesdb("").table("").row()]
-) { response in
- print(String(describing: response.payload))
-}
-
-// Subscribe to updates where person equals 'person1'
-let person1Votes = realtime.subscribe(
- channels: [Channel.tablesdb("").table("").row()],
- callback: { response in
- print(String(describing: response.payload))
- },
- queries: [Query.equal("person", value: ["person1"])]
-)
-
-// Subscribe to updates where person is not 'person1'
-let otherVotes = realtime.subscribe(
- channels: [Channel.tablesdb("").table("").row()],
- callback: { response in
- print(String(describing: response.payload))
- },
- queries: [Query.notEqual("person", value: "person1")]
-)
-```
-
-```client-android-kotlin
-import io.appwrite.Client
-import io.appwrite.Query
-import io.appwrite.services.Realtime
-import io.appwrite.extensions.Channel
-
-val client = Client(context)
- .setEndpoint("https://.cloud.appwrite.io/v1")
- .setProject("")
-
-val realtime = Realtime(client)
-
-// Subscribe to all updates
-val allVotes = realtime.subscribe(
- Channel.tablesdb("").table("").row()
-) {
- print(it.payload.toString())
-}
-
-// Subscribe to updates where person equals 'person1'
-val person1Votes = realtime.subscribe(
- Channel.tablesdb("").table("").row(),
- payloadType = Any::class.java,
- queries = setOf(Query.equal("person", listOf("person1")))
-) {
- print(it.payload.toString())
-}
-
-// Subscribe to updates where person is not 'person1'
-val otherVotes = realtime.subscribe(
- Channel.tablesdb("").table("").row(),
- payloadType = Any::class.java,
- queries = setOf(Query.notEqual("person", "person1"))
-) {
- print(it.payload.toString())
-}
-```
-
-{% /multicode %}
-
-## Supported queries {% #supported-queries %}
-
-The following query methods are supported for realtime filtering:
-
-{% table %}
-* Category
-* Queries
----
-* Comparison
-* `Query.equal()`, `Query.notEqual()`, `Query.greaterThan()`, `Query.greaterThanEqual()`, `Query.lessThan()`, `Query.lessThanEqual()`
----
-* Null checks
-* `Query.isNull()`, `Query.isNotNull()`
----
-* Logical
-* `Query.and()`, `Query.or()`
-{% /table %}
-
-# Payload {% #payload %}
-
-The payload from the subscription will contain following properties:
-
-{% table %}
-* Name
-* Type
-* Description
----
-* events
-* string[]
-* The [Appwrite events](/docs/advanced/platform/events) that triggered this update.
----
-* channels
-* string[]
-* An array of [channels](/docs/apis/realtime#channels) that can receive this message.
----
-* timestamp
-* string
-* The [ISO 8601 timestamp](https://en.wikipedia.org/wiki/ISO_8601) in UTC timezone from the server
----
-* payload
-* object
-* Payload contains the data equal to the response model.
-{% /table %}
-
-If you subscribe to the `rows` channel and a row the user is allowed to read is updated, you will receive an object containing information about the event and the updated row.
-
-The response will look like this:
-
-```json
-{
- "events": [
- "databases.default.tables.sample.rows.63c98b9baea0938e1206.update",
- "databases.*.tables.*.rows.*.update",
- "databases.default.tables.*.rows.63c98b9baea0938e1206.update",
- "databases.*.tables.*.rows.63c98b9baea0938e1206.update",
- "databases.*.tables.sample.rows.63c98b9baea0938e1206.update",
- "databases.default.tables.sample.rows.*.update",
- "databases.*.tables.sample.rows.*.update",
- "databases.default.tables.*.rows.*.update",
- "databases.default.tables.sample.rows.63c98b9baea0938e1206",
- "databases.*.tables.*.rows.*",
- "databases.default.tables.*.rows.63c98b9baea0938e1206",
- "databases.*.tables.*.rows.63c98b9baea0938e1206",
- "databases.*.tables.sample.rows.63c98b9baea0938e1206",
- "databases.default.tables.sample.rows.*",
- "databases.*.tables.sample.rows.*",
- "databases.default.tables.*.rows.*",
- "databases.default.tables.sample",
- "databases.*.tables.*",
- "databases.default.tables.*",
- "databases.*.tables.sample",
- "databases.default",
- "databases.*"
- ],
- "channels": [
- "rows",
- "databases.default.tables.sample.rows",
- "databases.default.tables.sample.rows.63c98b9baea0938e1206"
- ],
- "timestamp": "2023-01-19 18:30:04.051",
- "payload": {
- "ip": "127.0.0.1",
- "stringArray": [
- "sss"
- ],
- "email": "joe@example.com",
- "stringRequired": "req",
- "float": 3.3,
- "boolean": false,
- "integer": 3,
- "enum": "apple",
- "stringDefault": "default",
- "datetime": "2023-01-19T10:27:09.428+00:00",
- "url": "https://appwrite.io",
- "$id": "63c98b9baea0938e1206",
- "$createdAt": "2023-01-19T18:27:39.715+00:00",
- "$updatedAt": "2023-01-19T18:30:04.040+00:00",
- "$permissions": [],
- "$tableId": "sample",
- "$databaseId": "default"
- }
-}
-```
-
-# Channels {% #channels %}
-
-A list of all channels available you can subscribe to. When using `Channel` helpers, leaving an ID blank will subscribe using `*`.
-
-{% table %}
-* Channel
-* Channel Helper
-* Description
----
-* `account`
-* `Channel.account()`
-* All account related events (session create, name update...)
----
-* `tablesdb..tables..rows`
-* `Channel.tablesdb('').table('').row()`
-* Any create/update/delete events to any row in a table
----
-* `rows`
-* `Channel.rows()`
-* Any create/update/delete events to any row
----
-* `tablesdb..tables..rows.`
-* `Channel.tablesdb('').table('').row('')`
-* Any update/delete events to a given row
----
-* `files`
-* `Channel.files()`
-* Any create/update/delete events to any file
----
-* `buckets..files.`
-* `Channel.bucket('').file('')`
-* Any update/delete events to a given file of the given bucket
----
-* `buckets..files`
-* `Channel.bucket('').file()`
-* Any update/delete events to any file of the given bucket
----
-* `teams.*`
-* `Channel.teams()`
-* Any create/update/delete events to any team
----
-* `teams.`
-* `Channel.team('')`
-* Any update/delete events to a given team
----
-* `memberships`
-* `Channel.memberships()`
-* Any create/update/delete events to any membership
----
-* `memberships.`
-* `Channel.membership('')`
-* Any update/delete events to a given membership
----
-* `executions`
-* `Channel.executions()`
-* Any update to executions
----
-* `executions.`
-* `Channel.execution(ID)`
-* Any update to a given execution
----
-* `functions.`
-* `Channel.function('')`
-* Any execution event to a given function
-
-{% /table %}
-
-You can also filter events by appending event methods to the channel helpers:
-- `.create()` - Listen only to create events
-- `.update()` - Listen only to update events
-- `.delete()` - Listen only to delete events
-
-For example, `Channel.tablesdb('').table('').row('').update()` will only trigger on row updates.
-
-# Custom endpoint {% #custom-endpoint %}
-
-The SDK will guess the endpoint of the Realtime API when setting the endpoint of your Appwrite instance. If you are running Appwrite with a custom proxy and changed the route of the Realtime API, you can call the `setEndpointRealtime` method on the Client SDK and set your new endpoint value.
-
-By default the endpoint is `wss://.cloud.appwrite.io/v1/realtime`.
-
-{% multicode %}
-```client-web
-import { Client } from "appwrite";
-const client = new Client();
-
-client.setEndpointRealtime('wss://.cloud.appwrite.io/v1/realtime');
-```
-
-```client-flutter
-import 'package:appwrite/appwrite.dart';
-
-final client = Client();
-client.setEndpointRealtime('wss://.cloud.appwrite.io/v1/realtime');
-```
-
-```client-apple
-import Appwrite
-
-let client = Client()
-client.setEndpointRealtime("wss://.cloud.appwrite.io/v1/realtime")
-```
-
-```client-android-kotlin
-import io.appwrite.Client
-
-val client = Client(context)
-client.setEndpointRealtime("wss://.cloud.appwrite.io/v1/realtime")
-```
-
-{% /multicode %}
-
-# Limitations {% #limitations %}
-
-While the Realtime API offers robust capabilities, there are currently some limitations to be aware of in its implementation.
-
-## Subscription changes {% #subscription-changes %}
-
-The SDK creates a single WebSocket connection for all subscribed channels.
-Each time a channel is added or unsubscribed, the SDK currently creates a completely new connection and terminates the old one.
-Therefore, subscriptions to channels should always be done in conjunction with state management so as not to be unnecessarily
-built up several times by multiple components' life cycles.
-
-## Server SDKs {% #server-sdks %}
-
-We currently are not offering access to realtime with Server SDKs and an API key.
diff --git a/src/routes/docs/apis/realtime/authentication/+page.markdoc b/src/routes/docs/apis/realtime/authentication/+page.markdoc
new file mode 100644
index 0000000000..a60aff58d9
--- /dev/null
+++ b/src/routes/docs/apis/realtime/authentication/+page.markdoc
@@ -0,0 +1,23 @@
+---
+layout: article
+title: Authentication
+description: Learn how authentication works with Appwrite Realtime subscriptions and how to handle session-based access.
+---
+
+Realtime authenticates using an existing user session. If you authenticate **after** creating a subscription, the subscription will not receive updates for the newly authenticated user. You will need to re-create the subscription to work with the new user.
+
+More information and examples of authenticating users can be found in the dedicated [authentication docs](/docs/products/auth).
+
+{% info title="Permissions" %}
+All subscriptions are secured by the [permissions system](/docs/advanced/platform/permissions) offered by Appwrite, meaning a user will only receive updates to resources they have permission to access.
+
+Using `Role.any()` on read permissions will allow any client to receive updates.
+{% /info %}
+
+# Session lifecycle {% #session-lifecycle %}
+
+When working with Realtime subscriptions and authentication, keep the following in mind:
+
+1. **Create session first** - Always authenticate the user before creating subscriptions that require access to protected resources.
+2. **Re-subscribe on session change** - If a user logs out and a new user logs in, you must close existing subscriptions and create new ones for the new session.
+3. **Handle session expiry** - If a session expires, subscriptions tied to that session will stop receiving updates. Listen for session-related errors and re-authenticate when needed.
diff --git a/src/routes/docs/apis/realtime/channels/+page.markdoc b/src/routes/docs/apis/realtime/channels/+page.markdoc
new file mode 100644
index 0000000000..2903f2e0ce
--- /dev/null
+++ b/src/routes/docs/apis/realtime/channels/+page.markdoc
@@ -0,0 +1,182 @@
+---
+layout: article
+title: Channels
+description: Explore the available Realtime channels and learn how to use Channel helpers for type-safe subscriptions in Appwrite.
+---
+
+Channels define which Appwrite resources you want to subscribe to. When subscribing to a channel, you will receive callbacks for events related to that channel's resources. The Appwrite SDKs provide a `Channel` helper class to build type-safe channel subscriptions using a fluent API.
+
+# Channel helpers {% #channel-helpers %}
+
+Instead of manually writing channel strings, you can use the `Channel` helper class to build type-safe channel subscriptions. The helper provides a fluent API that makes it easier to construct channel strings and reduces errors.
+
+{% multicode %}
+```client-web
+import { Client, Realtime, Channel } from "appwrite";
+
+const client = new Client()
+ .setEndpoint('https://.cloud.appwrite.io/v1')
+ .setProject('');
+
+const realtime = new Realtime(client);
+
+// Subscribe to account channel
+const subscription = await realtime.subscribe(Channel.account(), response => {
+ console.log(response);
+});
+
+// Subscribe to a specific row
+const rowSubscription = await realtime.subscribe(
+ Channel.tablesdb('').table('').row(''),
+ response => {
+ console.log(response);
+ }
+);
+```
+
+```client-flutter
+import 'package:appwrite/appwrite.dart';
+
+final client = Client()
+ .setEndpoint('https://.cloud.appwrite.io/v1')
+ .setProject('');
+
+final realtime = Realtime(client);
+
+// Subscribe to account channel
+final subscription = realtime.subscribe([Channel.account()]);
+
+// Subscribe to a specific row
+final docSubscription = realtime.subscribe([
+ Channel.tablesdb('').table('').row('')
+]);
+```
+
+```client-apple
+import Appwrite
+
+let client = Client()
+ .setEndpoint("https://.cloud.appwrite.io/v1")
+ .setProject("")
+
+let realtime = Realtime(client)
+
+// Subscribe to account channel
+let subscription = realtime.subscribe(channels: [Channel.account()]) { response in
+ print(String(describing: response))
+}
+
+// Subscribe to a specific row
+let docSubscription = realtime.subscribe(
+ channels: [Channel.tablesdb("").table("").row("")]
+) { response in
+ print(String(describing: response))
+}
+```
+
+```client-android-kotlin
+import io.appwrite.Client
+import io.appwrite.services.Realtime
+import io.appwrite.extensions.Channel
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1")
+ .setProject("")
+
+val realtime = Realtime(client)
+
+// Subscribe to account channel
+val subscription = realtime.subscribe(Channel.account()) {
+ print(it.toString())
+}
+
+// Subscribe to a specific row
+val docSubscription = realtime.subscribe(
+ Channel.tablesdb("").table("").row("")
+) {
+ print(it.toString())
+}
+```
+
+{% /multicode %}
+
+The `Channel` helper supports all available channels and allows you to:
+- Build channels with a fluent, chainable API
+- Optionally specify resource IDs (omit IDs to subscribe to all resources)
+- Add event filters like `.create()`, `.update()`, or `.delete()`
+
+# Available channels {% #available-channels %}
+
+A list of all channels available you can subscribe to. When using `Channel` helpers, leaving an ID blank will subscribe using `*`.
+
+{% table %}
+* Channel
+* Channel Helper
+* Description
+---
+* `account`
+* `Channel.account()`
+* All account related events (session create, name update...)
+---
+* `tablesdb..tables..rows`
+* `Channel.tablesdb('').table('').row()`
+* Any create/update/delete events to any row in a table
+---
+* `rows`
+* `Channel.rows()`
+* Any create/update/delete events to any row
+---
+* `tablesdb..tables..rows.`
+* `Channel.tablesdb('').table('').row('')`
+* Any update/delete events to a given row
+---
+* `files`
+* `Channel.files()`
+* Any create/update/delete events to any file
+---
+* `buckets..files.`
+* `Channel.bucket('').file('')`
+* Any update/delete events to a given file of the given bucket
+---
+* `buckets..files`
+* `Channel.bucket('').file()`
+* Any update/delete events to any file of the given bucket
+---
+* `teams.*`
+* `Channel.teams()`
+* Any create/update/delete events to any team
+---
+* `teams.`
+* `Channel.team('')`
+* Any update/delete events to a given team
+---
+* `memberships`
+* `Channel.memberships()`
+* Any create/update/delete events to any membership
+---
+* `memberships.`
+* `Channel.membership('')`
+* Any update/delete events to a given membership
+---
+* `executions`
+* `Channel.executions()`
+* Any update to executions
+---
+* `executions.`
+* `Channel.execution(ID)`
+* Any update to a given execution
+---
+* `functions.`
+* `Channel.function('')`
+* Any execution event to a given function
+
+{% /table %}
+
+# Event filters {% #event-filters %}
+
+You can also filter events by appending event methods to the channel helpers:
+- `.create()` - Listen only to create events
+- `.update()` - Listen only to update events
+- `.delete()` - Listen only to delete events
+
+For example, `Channel.tablesdb('').table('').row('').update()` will only trigger on row updates.
diff --git a/src/routes/docs/apis/realtime/custom-endpoint/+page.markdoc b/src/routes/docs/apis/realtime/custom-endpoint/+page.markdoc
new file mode 100644
index 0000000000..676eaeef88
--- /dev/null
+++ b/src/routes/docs/apis/realtime/custom-endpoint/+page.markdoc
@@ -0,0 +1,40 @@
+---
+layout: article
+title: Custom endpoint
+description: Learn how to configure a custom WebSocket endpoint for the Appwrite Realtime API when using a custom proxy.
+---
+
+The SDK will guess the endpoint of the Realtime API when setting the endpoint of your Appwrite instance. If you are running Appwrite with a custom proxy and changed the route of the Realtime API, you can call the `setEndpointRealtime` method on the Client SDK and set your new endpoint value.
+
+By default the endpoint is `wss://.cloud.appwrite.io/v1/realtime`.
+
+{% multicode %}
+```client-web
+import { Client } from "appwrite";
+const client = new Client();
+
+client.setEndpointRealtime('wss://.cloud.appwrite.io/v1/realtime');
+```
+
+```client-flutter
+import 'package:appwrite/appwrite.dart';
+
+final client = Client();
+client.setEndpointRealtime('wss://.cloud.appwrite.io/v1/realtime');
+```
+
+```client-apple
+import Appwrite
+
+let client = Client()
+client.setEndpointRealtime("wss://.cloud.appwrite.io/v1/realtime")
+```
+
+```client-android-kotlin
+import io.appwrite.Client
+
+val client = Client(context)
+client.setEndpointRealtime("wss://.cloud.appwrite.io/v1/realtime")
+```
+
+{% /multicode %}
diff --git a/src/routes/docs/apis/realtime/limitations/+page.markdoc b/src/routes/docs/apis/realtime/limitations/+page.markdoc
new file mode 100644
index 0000000000..817da25fda
--- /dev/null
+++ b/src/routes/docs/apis/realtime/limitations/+page.markdoc
@@ -0,0 +1,18 @@
+---
+layout: article
+title: Limitations
+description: Learn about the current limitations of the Appwrite Realtime API and how to work around them.
+---
+
+While the Realtime API offers robust capabilities, there are currently some limitations to be aware of in its implementation.
+
+# Subscription changes {% #subscription-changes %}
+
+The SDK creates a single WebSocket connection for all subscribed channels.
+Each time a channel is added or unsubscribed, the SDK currently creates a completely new connection and terminates the old one.
+Therefore, subscriptions to channels should always be done in conjunction with state management so as not to be unnecessarily
+built up several times by multiple components' life cycles.
+
+# Server SDKs {% #server-sdks %}
+
+We currently are not offering access to realtime with Server SDKs and an API key.
diff --git a/src/routes/docs/apis/realtime/payload/+page.markdoc b/src/routes/docs/apis/realtime/payload/+page.markdoc
new file mode 100644
index 0000000000..88f8c45a5f
--- /dev/null
+++ b/src/routes/docs/apis/realtime/payload/+page.markdoc
@@ -0,0 +1,95 @@
+---
+layout: article
+title: Payload
+description: Understand the structure of Appwrite Realtime subscription payloads and learn how to work with the response data.
+---
+
+When you receive an update from a Realtime subscription, the payload contains information about the event and the affected resource. Understanding this structure helps you handle updates effectively in your application.
+
+# Response structure {% #response-structure %}
+
+The payload from the subscription will contain following properties:
+
+{% table %}
+* Name
+* Type
+* Description
+---
+* events
+* string[]
+* The [Appwrite events](/docs/advanced/platform/events) that triggered this update.
+---
+* channels
+* string[]
+* An array of [channels](/docs/apis/realtime/channels) that can receive this message.
+---
+* timestamp
+* string
+* The [ISO 8601 timestamp](https://en.wikipedia.org/wiki/ISO_8601) in UTC timezone from the server
+---
+* payload
+* object
+* Payload contains the data equal to the response model.
+{% /table %}
+
+# Example {% #example %}
+
+If you subscribe to the `rows` channel and a row the user is allowed to read is updated, you will receive an object containing information about the event and the updated row.
+
+The response will look like this:
+
+```json
+{
+ "events": [
+ "tablesdb.default.tables.sample.rows.63c98b9baea0938e1206.update",
+ "tablesdb.*.tables.*.rows.*.update",
+ "tablesdb.default.tables.*.rows.63c98b9baea0938e1206.update",
+ "tablesdb.*.tables.*.rows.63c98b9baea0938e1206.update",
+ "tablesdb.*.tables.sample.rows.63c98b9baea0938e1206.update",
+ "tablesdb.default.tables.sample.rows.*.update",
+ "tablesdb.*.tables.sample.rows.*.update",
+ "tablesdb.default.tables.*.rows.*.update",
+ "tablesdb.default.tables.sample.rows.63c98b9baea0938e1206",
+ "tablesdb.*.tables.*.rows.*",
+ "tablesdb.default.tables.*.rows.63c98b9baea0938e1206",
+ "tablesdb.*.tables.*.rows.63c98b9baea0938e1206",
+ "tablesdb.*.tables.sample.rows.63c98b9baea0938e1206",
+ "tablesdb.default.tables.sample.rows.*",
+ "tablesdb.*.tables.sample.rows.*",
+ "tablesdb.default.tables.*.rows.*",
+ "tablesdb.default.tables.sample",
+ "tablesdb.*.tables.*",
+ "tablesdb.default.tables.*",
+ "tablesdb.*.tables.sample",
+ "tablesdb.default",
+ "tablesdb.*"
+ ],
+ "channels": [
+ "rows",
+ "tablesdb.default.tables.sample.rows",
+ "tablesdb.default.tables.sample.rows.63c98b9baea0938e1206"
+ ],
+ "timestamp": "2023-01-19 18:30:04.051",
+ "payload": {
+ "ip": "127.0.0.1",
+ "stringArray": [
+ "sss"
+ ],
+ "email": "joe@example.com",
+ "stringRequired": "req",
+ "float": 3.3,
+ "boolean": false,
+ "integer": 3,
+ "enum": "apple",
+ "stringDefault": "default",
+ "datetime": "2023-01-19T10:27:09.428+00:00",
+ "url": "https://appwrite.io",
+ "$id": "63c98b9baea0938e1206",
+ "$createdAt": "2023-01-19T18:27:39.715+00:00",
+ "$updatedAt": "2023-01-19T18:30:04.040+00:00",
+ "$permissions": [],
+ "$tableId": "sample",
+ "$databaseId": "default"
+ }
+}
+```
diff --git a/src/routes/docs/apis/realtime/queries/+page.markdoc b/src/routes/docs/apis/realtime/queries/+page.markdoc
new file mode 100644
index 0000000000..ab97bc912c
--- /dev/null
+++ b/src/routes/docs/apis/realtime/queries/+page.markdoc
@@ -0,0 +1,177 @@
+---
+layout: article
+title: Queries
+description: Filter realtime events using queries. Use familiar SDK query methods to receive only the updates that match your conditions.
+---
+
+You can filter realtime events by passing queries as a third parameter when subscribing. Events are filtered server-side based on your queries, so your callback only receives updates that match your conditions. This allows you to use familiar SDK queries like `Query.equal` to automatically filter events instead of filtering manually in your callback.
+
+{% multicode %}
+```client-web
+import { Client, Realtime, Channel, Query } from "appwrite";
+
+const client = new Client()
+ .setEndpoint('https://.cloud.appwrite.io/v1')
+ .setProject('');
+
+const realtime = new Realtime(client);
+
+// Subscribe to all updates
+const allVotes = await realtime.subscribe(
+ Channel.tablesdb('').table('').row(),
+ response => {
+ console.log(response.payload);
+ }
+);
+
+// Subscribe to updates where person equals 'person1'
+const person1Votes = await realtime.subscribe(
+ Channel.tablesdb('').table('').row(),
+ response => {
+ console.log(response.payload);
+ },
+ [Query.equal('person', ['person1'])]
+);
+
+// Subscribe to updates where person is not 'person1'
+const otherVotes = await realtime.subscribe(
+ Channel.tablesdb('').table('').row(),
+ response => {
+ console.log(response.payload);
+ },
+ [Query.notEqual('person', 'person1')]
+);
+```
+
+```client-flutter
+import 'package:appwrite/appwrite.dart';
+
+final client = Client()
+ .setEndpoint('https://.cloud.appwrite.io/v1')
+ .setProject('');
+
+final realtime = Realtime(client);
+
+// Subscribe to all updates
+final allVotes = realtime.subscribe(
+ [Channel.tablesdb('').table('').row()]
+);
+
+allVotes.stream.listen((response) {
+ print(response.payload);
+});
+
+// Subscribe to updates where person equals 'person1'
+final person1Votes = realtime.subscribe(
+ [Channel.tablesdb('').table('').row()],
+ queries: [Query.equal('person', ['person1'])]
+);
+
+person1Votes.stream.listen((response) {
+ print(response.payload);
+});
+
+// Subscribe to updates where person is not 'person1'
+final otherVotes = realtime.subscribe(
+ [Channel.tablesdb('').table('').row()],
+ queries: [Query.notEqual('person', 'person1')]
+);
+
+otherVotes.stream.listen((response) {
+ print(response.payload);
+});
+```
+
+```client-apple
+import Appwrite
+import AppwriteModels
+
+let client = Client()
+ .setEndpoint("https://.cloud.appwrite.io/v1")
+ .setProject("")
+
+let realtime = Realtime(client)
+
+// Subscribe to all updates
+let allVotes = realtime.subscribe(
+ channels: [Channel.tablesdb("").table("").row()]
+) { response in
+ print(String(describing: response.payload))
+}
+
+// Subscribe to updates where person equals 'person1'
+let person1Votes = realtime.subscribe(
+ channels: [Channel.tablesdb("").table("").row()],
+ callback: { response in
+ print(String(describing: response.payload))
+ },
+ queries: [Query.equal("person", value: ["person1"])]
+)
+
+// Subscribe to updates where person is not 'person1'
+let otherVotes = realtime.subscribe(
+ channels: [Channel.tablesdb("").table("").row()],
+ callback: { response in
+ print(String(describing: response.payload))
+ },
+ queries: [Query.notEqual("person", value: "person1")]
+)
+```
+
+```client-android-kotlin
+import io.appwrite.Client
+import io.appwrite.Query
+import io.appwrite.services.Realtime
+import io.appwrite.extensions.Channel
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1")
+ .setProject("")
+
+val realtime = Realtime(client)
+
+// Subscribe to all updates
+val allVotes = realtime.subscribe(
+ Channel.tablesdb("").table("").row()
+) {
+ print(it.payload.toString())
+}
+
+// Subscribe to updates where person equals 'person1'
+val person1Votes = realtime.subscribe(
+ Channel.tablesdb("").table("").row(),
+ payloadType = Any::class.java,
+ queries = setOf(Query.equal("person", listOf("person1")))
+) {
+ print(it.payload.toString())
+}
+
+// Subscribe to updates where person is not 'person1'
+val otherVotes = realtime.subscribe(
+ Channel.tablesdb("").table("").row(),
+ payloadType = Any::class.java,
+ queries = setOf(Query.notEqual("person", "person1"))
+) {
+ print(it.payload.toString())
+}
+```
+
+{% /multicode %}
+
+# Supported queries {% #supported-queries %}
+
+The following query methods are supported for realtime filtering:
+
+{% table %}
+* Category
+* Queries
+---
+* Comparison
+* `Query.equal()`, `Query.notEqual()`, `Query.greaterThan()`, `Query.greaterThanEqual()`, `Query.lessThan()`, `Query.lessThanEqual()`
+---
+* Null checks
+* `Query.isNull()`, `Query.isNotNull()`
+---
+* Logical
+* `Query.and()`, `Query.or()`
+{% /table %}
diff --git a/src/routes/docs/apis/realtime/subscribe/+page.markdoc b/src/routes/docs/apis/realtime/subscribe/+page.markdoc
new file mode 100644
index 0000000000..aa9f29c0f0
--- /dev/null
+++ b/src/routes/docs/apis/realtime/subscribe/+page.markdoc
@@ -0,0 +1,244 @@
+---
+layout: article
+title: Subscribe
+description: Learn how to subscribe to realtime events from Appwrite services. Subscribe to single or multiple channels and manage your subscriptions.
+---
+
+The Appwrite Realtime API lets you subscribe to events from any Appwrite service through [channels](/docs/apis/realtime/channels). You can subscribe to a single channel, multiple channels at once, and unsubscribe when you no longer need updates.
+
+# Subscribe to a channel {% #subscribe-to-a-channel %}
+
+In this example we are subscribing to all updates related to our account by using the `account` channel. This will be triggered by any update related to the authenticated user, like updating the user's name or e-mail address.
+
+{% multicode %}
+```client-web
+import { Client, Realtime, Channel } from "appwrite";
+
+const client = new Client()
+ .setEndpoint('https://.cloud.appwrite.io/v1')
+ .setProject('');
+
+const realtime = new Realtime(client);
+
+const subscription = await realtime.subscribe(Channel.account(), response => {
+ // Callback will be executed on all account events.
+ console.log(response);
+});
+```
+
+```client-flutter
+import 'package:appwrite/appwrite.dart';
+
+final client = Client()
+ .setEndpoint('https://.cloud.appwrite.io/v1')
+ .setProject('');
+
+final realtime = Realtime(client);
+
+final subscription = realtime.subscribe([Channel.account()]);
+
+subscription.stream.listen((response) {
+ // Callback will be executed on all account events.
+ print(response);
+})
+```
+
+```client-apple
+import Appwrite
+import AppwriteModels
+
+let client = Client()
+ .setEndpoint("https://.cloud.appwrite.io/v1")
+ .setProject("")
+
+let realtime = Realtime(client)
+
+let subscription = realtime.subscribe(channels: [Channel.account()]) { response in
+ // Callback will be executed on all account events.
+ print(String(describing: response))
+}
+```
+
+```client-android-kotlin
+import io.appwrite.Client
+import io.appwrite.services.Realtime
+import io.appwrite.extensions.Channel
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1")
+ .setProject("")
+
+val realtime = Realtime(client)
+
+val subscription = realtime.subscribe(Channel.account()) {
+ // Callback will be executed on all account events.
+ print(it.payload.toString())
+}
+```
+
+{% /multicode %}
+
+# Subscribe to multiple channels {% #subscribe-to-multiple-channels %}
+
+You can also listen to multiple channels at once by passing an array of channels. This will trigger the callback for any events for all channels passed.
+
+In this example we are listening to a specific row and all files by subscribing to `Channel.tablesdb("").table("").row("")` and `Channel.files()` channels.
+
+{% multicode %}
+```client-web
+import { Client, Realtime, Channel } from "appwrite";
+
+const client = new Client()
+ .setEndpoint('https://.cloud.appwrite.io/v1')
+ .setProject('');
+
+const realtime = new Realtime(client);
+
+const subscription = await realtime.subscribe([
+ Channel.tablesdb('').table('').row(''),
+ Channel.files()
+], response => {
+ // Callback will be executed on changes for the row and all files.
+ console.log(response);
+});
+```
+
+```client-flutter
+import 'package:appwrite/appwrite.dart';
+
+final client = Client()
+ .setEndpoint('https://.cloud.appwrite.io/v1')
+ .setProject('');
+
+final realtime = Realtime(client);
+
+final subscription = realtime.subscribe([
+ Channel.tablesdb('').table('').row(''),
+ Channel.files()
+]);
+
+subscription.stream.listen((response) {
+ // Callback will be executed on changes for the row and all files.
+ print(response);
+})
+```
+
+```client-apple
+import Appwrite
+import AppwriteModels
+
+let client = Client()
+ .setEndpoint("https://.cloud.appwrite.io/v1")
+ .setProject("")
+
+let realtime = Realtime(client)
+
+realtime.subscribe(channels: [
+ Channel.tablesdb("").table("").row(""),
+ Channel.files()
+]) { response in
+ // Callback will be executed on changes for the row and all files.
+ print(String(describing: response))
+}
+```
+
+```client-android-kotlin
+import io.appwrite.Client
+import io.appwrite.services.Realtime
+import io.appwrite.extensions.Channel
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1")
+ .setProject("")
+val realtime = Realtime(client)
+
+realtime.subscribe(
+ Channel.tablesdb("").table("").row(""),
+ Channel.files()
+) {
+ // Callback will be executed on changes for the row and all files.
+ print(it.toString())
+}
+```
+
+{% /multicode %}
+
+# Unsubscribe {% #unsubscribe %}
+
+If you no longer want to receive updates from a subscription, you can unsubscribe so that your callbacks are no longer called. Leaving old subscriptions alive and resubscribing can result in duplicate subscriptions and cause race conditions.
+
+{% multicode %}
+```client-web
+import { Client, Realtime, Channel } from "appwrite";
+
+const client = new Client()
+ .setEndpoint('https://.cloud.appwrite.io/v1')
+ .setProject('');
+
+const realtime = new Realtime(client);
+
+const subscription = await realtime.subscribe(Channel.files(), response => {
+ // Callback will be executed on changes for all files.
+ console.log(response);
+});
+
+// Closes the subscription.
+await subscription.close();
+```
+
+```client-flutter
+import 'package:appwrite/appwrite.dart';
+
+final client = Client()
+ .setEndpoint('https://.cloud.appwrite.io/v1')
+ .setProject('');
+
+final realtime = Realtime(client);
+
+final subscription = realtime.subscribe([Channel.files()]);
+
+subscription.stream.listen((response) {
+ // Callback will be executed on changes for all files.
+ print(response);
+})
+
+// Closes the subscription.
+subscription.close();
+```
+
+```client-apple
+import Appwrite
+
+let client = Client()
+let realtime = Realtime(client)
+
+let subscription = realtime.subscribe(channels: [Channel.files()]) { response in
+ // Callback will be executed on changes for all files.
+ print(response.toString())
+}
+
+// Closes the subscription.
+subscription.close()
+```
+
+```client-android-kotlin
+import io.appwrite.Client
+import io.appwrite.services.Realtime
+import io.appwrite.extensions.Channel
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1")
+ .setProject("")
+
+val realtime = Realtime(client)
+
+val subscription = realtime.subscribe(Channel.files()) {
+ // Callback will be executed on changes for all files.
+ print(it.toString())
+}
+
+// Closes the subscription.
+subscription.close()
+```
+
+{% /multicode %}
diff --git a/src/routes/docs/apis/rest/+layout.svelte b/src/routes/docs/apis/rest/+layout.svelte
new file mode 100644
index 0000000000..93e22c8ceb
--- /dev/null
+++ b/src/routes/docs/apis/rest/+layout.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+
+