From fb2bab03f76245251b82d4404bf48a6c7cd2ad94 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 Jan 2026 14:02:50 +0530 Subject: [PATCH 1/2] updated realtime doc --- src/routes/docs/apis/realtime/+page.markdoc | 321 +++++++++++++------- 1 file changed, 211 insertions(+), 110 deletions(-) diff --git a/src/routes/docs/apis/realtime/+page.markdoc b/src/routes/docs/apis/realtime/+page.markdoc index 86b52ed7d6..0fe2e8c596 100644 --- a/src/routes/docs/apis/realtime/+page.markdoc +++ b/src/routes/docs/apis/realtime/+page.markdoc @@ -12,14 +12,14 @@ This lets you build an interactive and responsive user experience by providing i {% multicode %} ```client-web -import { Client } from "appwrite"; +import { Client, Channel } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') .setProject(''); // Subscribe to files channel -client.subscribe('files', response => { +client.subscribe(Channel.bucket().file(), response => { if(response.events.includes('buckets.*.files.*.create')) { // Log when a new file is uploaded console.log(response.payload); @@ -37,7 +37,7 @@ final client = Client() final realtime = Realtime(client); // Subscribe to files channel -final subscription = realtime.subscribe(['files']); +final subscription = realtime.subscribe([Channel.bucket().file()]); subscription.stream.listen((response) { if(response.events.contains('buckets.*.files.*.create')) { @@ -58,8 +58,8 @@ let client = Client() let realtime = Realtime(client) // Subscribe to files channel -let subscription = realtime.subscribe(channels: ["files"]) { response in - if (response.events!.contains("buckets.*.files.*.create")) { +let subscription = realtime.subscribe(channels: [Channel.bucket().file()]) { response in + if (message.events!.contains("buckets.*.files.*.create")) { // Log when a new file is uploaded print(String(describing: response)) } @@ -69,6 +69,7 @@ let subscription = realtime.subscribe(channels: ["files"]) { response in ```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") @@ -77,7 +78,7 @@ val client = Client(context) val realtime = Realtime(client) // Subscribe to files channel -val subscription = realtime.subscribe("files") { +val subscription = realtime.subscribe(Channel.bucket().file()) { if(it.events.contains("buckets.*.files.*.create")) { // Log when a new file is uploaded print(it.payload.toString()); @@ -89,10 +90,106 @@ val subscription = realtime.subscribe("files") { 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. +If you subscribe to a channel, you will receive callbacks for a variety of events related to the channel. The events attribute 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, Channel } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject(''); + +// Subscribe to account channel +client.subscribe(Channel.account(), response => { + console.log(response); +}); + +// Subscribe to a specific row +client.subscribe( + Channel.tablesdb('db1').table('table1').row('row1'), + 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('db1').table('table1').row('row1') +]); +``` + +```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("db1").table("table1").row("row1")] +) { 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("db1").table("table1").row("row1") +) { + 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. @@ -114,13 +211,13 @@ In this example we are subscribing to all updates related to our account by usin {% multicode %} ```client-web -import { Client } from "appwrite"; +import { Client, Channel } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') .setProject(''); -client.subscribe('account', response => { +client.subscribe(Channel.account(), response => { // Callback will be executed on all account events. console.log(response); }); @@ -135,7 +232,7 @@ final client = Client() final realtime = Realtime(client); -final subscription = realtime.subscribe(['account']); +final subscription = realtime.subscribe([Channel.account()]); subscription.stream.listen((response) { // Callback will be executed on all account events. @@ -153,7 +250,7 @@ let client = Client() let realtime = Realtime(client) -let subscription = realtime.subscribe(channel: "account") { response in +let subscription = realtime.subscribe(channels: [Channel.account()]) { response in // Callback will be executed on all account events. print(String(describing: response)) } @@ -162,6 +259,7 @@ let subscription = realtime.subscribe(channel: "account") { response in ```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") @@ -169,7 +267,7 @@ val client = Client(context) val realtime = Realtime(client) -val subscription = realtime.subscribe("account") { +val subscription = realtime.subscribe(Channel.account()) { // Callback will be executed on all account events. print(it.payload.toString()) } @@ -181,18 +279,21 @@ val subscription = realtime.subscribe("account") { 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 the `databases..tables..rows.` and `files` channels. +In this example we are listening to a specific row and all files by subscribing to multiple channels. {% multicode %} ```client-web -import { Client } from "appwrite"; +import { Client, Channel } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') .setProject(''); -client.subscribe(['databases..tables..rows.', 'files'], response => { - // Callback will be executed on changes for the specific row and all files. +client.subscribe([ + Channel.tablesdb('db1').table('table1').row('row1'), + Channel.bucket().file() +], response => { + // Callback will be executed on changes for the row and all files. console.log(response); }); ``` @@ -206,10 +307,13 @@ final client = Client() final realtime = Realtime(client); -final subscription = realtime.subscribe(['databases..tables..rows.', 'files']); +final subscription = realtime.subscribe([ + Channel.tablesdb('db1').table('table1').row('row1'), + Channel.bucket().file() +]); subscription.stream.listen((response) { - // Callback will be executed on changes for the specific row and all files. + // Callback will be executed on changes for the row and all files. print(response); }) ``` @@ -224,8 +328,11 @@ let client = Client() let realtime = Realtime(client) -realtime.subscribe(channels: ["databases..tables..rows.", "files"]) { response in - // Callback will be executed on changes for the specific row and all files. +realtime.subscribe(channels: [ + Channel.tablesdb("db1").table("table1").row("row1"), + Channel.bucket().file() +]) { response in + // Callback will be executed on changes for the row and all files. print(String(describing: response)) } ``` @@ -233,14 +340,18 @@ realtime.subscribe(channels: ["databases..tables..rows..cloud.appwrite.io/v1") .setProject("") val realtime = Realtime(client) -realtime.subscribe(listOf("databases..tables..rows.", "files")) { - // Callback will be executed on changes for the specific row and all files. +realtime.subscribe( + Channel.tablesdb("db1").table("table1").row("row1"), + Channel.bucket().file() +) { + // Callback will be executed on changes for the row and all files. print(it.toString()) } ``` @@ -253,13 +364,13 @@ If you no longer want to receive updates from a subscription, you can unsubscrib {% multicode %} ```client-web -import { Client } from "appwrite"; +import { Client, Channel } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') .setProject(''); -const unsubscribe = client.subscribe('files', response => { +const unsubscribe = client.subscribe(Channel.bucket().file(), response => { // Callback will be executed on changes for all files. console.log(response); }); @@ -277,7 +388,7 @@ final client = Client() final realtime = Realtime(client); -final subscription = realtime.subscribe(['files']); +final subscription = realtime.subscribe([Channel.bucket().file()]); subscription.stream.listen((response) { // Callback will be executed on changes for all files. @@ -294,7 +405,7 @@ import Appwrite let client = Client() let realtime = Realtime(client) -let subscription = realtime.subscribe(channel: "files") { response in +let subscription = realtime.subscribe(channels: [Channel.bucket().file()]) { response in // Callback will be executed on changes for all files. print(response.toString()) } @@ -306,6 +417,7 @@ 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") @@ -313,7 +425,7 @@ val client = Client(context) val realtime = Realtime(client) -val subscription = realtime.subscribe("files") { +val subscription = realtime.subscribe(Channel.bucket().file()) { // Callback will be executed on changes for all files. print(it.toString()) } @@ -350,40 +462,40 @@ The payload from the subscription will contain following properties: * 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. +If you subscribe to the `documents` channel and a document the user is allowed to read is updated, you will receive an object containing information about the event and the updated document. 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.collections.sample.documents.63c98b9baea0938e1206.update", + "databases.*.collections.*.documents.*.update", + "databases.default.collections.*.documents.63c98b9baea0938e1206.update", + "databases.*.collections.*.documents.63c98b9baea0938e1206.update", + "databases.*.collections.sample.documents.63c98b9baea0938e1206.update", + "databases.default.collections.sample.documents.*.update", + "databases.*.collections.sample.documents.*.update", + "databases.default.collections.*.documents.*.update", + "databases.default.collections.sample.documents.63c98b9baea0938e1206", + "databases.*.collections.*.documents.*", + "databases.default.collections.*.documents.63c98b9baea0938e1206", + "databases.*.collections.*.documents.63c98b9baea0938e1206", + "databases.*.collections.sample.documents.63c98b9baea0938e1206", + "databases.default.collections.sample.documents.*", + "databases.*.collections.sample.documents.*", + "databases.default.collections.*.documents.*", + "databases.default.collections.sample", + "databases.*.collections.*", + "databases.default.collections.*", + "databases.*.collections.sample", "databases.default", "databases.*" ], "channels": [ - "rows", - "databases.default.tables.sample.rows", - "databases.default.tables.sample.rows.63c98b9baea0938e1206" + "documents", + "databases.default.collections.sample.documents", + "databases.default.collections.sample.documents.63c98b9baea0938e1206" ], "timestamp": "2023-01-19 18:30:04.051", "payload": { @@ -404,7 +516,7 @@ The response will look like this: "$createdAt": "2023-01-19T18:27:39.715+00:00", "$updatedAt": "2023-01-19T18:30:04.040+00:00", "$permissions": [], - "$tableId": "sample", + "$collectionId": "sample", "$databaseId": "default" } } @@ -412,89 +524,78 @@ The response will look like this: # Channels {% #channels %} -A list of channels you can subscribe to. Replace `` with your resource ID or use `*` for wildcards. - -## Account {% #account %} +A list of all channels available you can subscribe to. IDs cannot be wildcards. {% table %} * Channel +* Channel Helper * Description --- * `account` +* `Channel.account()` * All account related events (session create, name update...) - -{% /table %} - -## Databases {% #databases %} - -{% table %} -* Channel -* Description --- -* `rows` -* Any create/update/delete events to any row ---- -* `databases..tables..rows` +* `databases.[ID].collections.[ID].documents` +* `Channel.tablesdb(ID).table(ID).row()` * Any create/update/delete events to any row in a table --- -* `databases..tables..rows.` -* Any create/update/delete events to a given row -{% /table %} - -## Storage {% #storage %} - -{% table %} -* Channel -* Description +* `documents` +* `Channel.tablesdb().table().row()` +* Any create/update/delete events to any row +--- +* `databases.[ID].collections.[ID].documents.[ID]` +* `Channel.tablesdb(ID).table(ID).row(ID)` +* Any update/delete events to a given row --- * `files` +* `Channel.bucket().file()` * Any create/update/delete events to any file --- -* `buckets..files` -* Any create/update/delete events to any file of the given bucket +* `buckets.[ID].files.[ID]` +* `Channel.bucket(ID).file(ID)` +* Any update/delete events to a given file of the given bucket --- -* `buckets..files.` -* Any create/update/delete events to a given file of the given bucket - -{% /table %} - -## Functions {% #functions %} - -{% table %} -* Channel -* Description +* `buckets.[ID].files` +* `Channel.bucket(ID).file()` +* Any update/delete events to any file of the given bucket --- -* `executions` -* Any execution event +* `teams` +* `Channel.team()` +* Any create/update/delete events to a any team --- -* `executions.` -* Any execution event to a given execution +* `teams.[ID]` +* `Channel.team(ID)` +* Any update/delete events to a given team --- -* `functions.` -* Any execution event to a given function - -{% /table %} - -## Teams & Memberships {% #teams %} - -{% table %} -* Channel -* Description +* `memberships` +* `Channel.membership()` +* Any create/update/delete events to a any membership --- -* `teams` -* Any create/update/delete events to any team +* `memberships.[ID]` +* `Channel.membership(ID)` +* Any update/delete events to a given membership --- -* `teams.` -* Any create/update/delete events to a given team +* `executions` +* `Channel.function().execution()` +* Any update to executions --- -* `memberships` -* Any create/update/delete events to any membership +* `executions.[ID]` +* `Channel.function().execution(ID)` +* Any update to a given execution --- -* `memberships.` -* Any create/update/delete events to a given membership +* `functions.[ID]` +* `Channel.function(ID)` +* 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('db1').table('table1').row('row1').update().toString()` 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. From 8a8278e493d0912899230cbf0e27c3788728f254 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 Jan 2026 14:04:16 +0530 Subject: [PATCH 2/2] typo --- src/routes/docs/apis/realtime/+page.markdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/docs/apis/realtime/+page.markdoc b/src/routes/docs/apis/realtime/+page.markdoc index 0fe2e8c596..da4307d48b 100644 --- a/src/routes/docs/apis/realtime/+page.markdoc +++ b/src/routes/docs/apis/realtime/+page.markdoc @@ -561,7 +561,7 @@ A list of all channels available you can subscribe to. IDs cannot be wildcards. --- * `teams` * `Channel.team()` -* Any create/update/delete events to a any team +* Any create/update/delete events to any team --- * `teams.[ID]` * `Channel.team(ID)` @@ -569,7 +569,7 @@ A list of all channels available you can subscribe to. IDs cannot be wildcards. --- * `memberships` * `Channel.membership()` -* Any create/update/delete events to a any membership +* Any create/update/delete events to any membership --- * `memberships.[ID]` * `Channel.membership(ID)`