Merge branch '1.5.x' of https://github.com/appwrite/website into announcement-messaging

This commit is contained in:
Torsten Dittmann
2024-02-25 18:57:20 +01:00
204 changed files with 16078 additions and 1080 deletions

View File

@@ -204,6 +204,27 @@ Available sizes are `s`, `m`, `l` and `xl`. Default: `s`.
#### Only Light/Dark Theme
```
{% only_dark %}I am only shown in Dark Theme{% /only_dark %}
{% only_light %}I am only shown in Light Theme{% /only_light %}
{% only_dark %}
![Project settings screen](/images/docs/platform/dark/create-api-key.png)
{% /only_dark %}
{% only_light %}
![Project settings screen](/images/docs/platform/create-api-key.png)
{% /only_light %}
```
#### Cards
{% cards %}
{% cards_item href="/docs/quick-starts/react" title="React" %}
Get started with Appwrite and React
{% /cards_item %}
{% cards_item href="/docs/quick-starts/vue" title="Vue.js" %}
Get started with Appwrite and Vue.js
{% /cards_item %}
{% cards_item href="/docs/quick-starts/nuxt" title="Nuxt" %}
Get started with Appwrite and Nuxt
{% /cards_item %}
{% cards_item href="/docs/quick-starts/sveltekit" title="SvelteKit" %}
Get started with Appwrite and SvelteKit
{% /cards_item %}
{% /cards %}

1352
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,8 @@ import MarkdownIt from 'markdown-it';
const md = new MarkdownIt('commonmark');
export function parse(content: string): string {
try {
const tokens = md.parse(content, null);
return md.renderer.render(
transform_tokens(tokens),
{
@@ -11,6 +11,11 @@ export function parse(content: string): string {
},
null
);
} catch (error) {
console.error('An error occurred while parsing the markdown content:', error);
console.error('Content:', content);
return '';
}
}
function transform_tokens(tokens: ReturnType<typeof md.parse>): ReturnType<typeof md.parse> {

View File

@@ -15,6 +15,7 @@ export enum Service {
Avatars = 'avatars',
Databases = 'databases',
Functions = 'functions',
Messaging = 'messaging',
Health = 'health',
Locale = 'locale',
Storage = 'storage',
@@ -107,6 +108,7 @@ export const serviceMap: Record<Service, string> = {
[Service.Avatars]: 'Avatars',
[Service.Databases]: 'Databases',
[Service.Functions]: 'Functions',
[Service.Messaging]: 'Messaging',
[Service.Health]: 'Health',
[Service.Locale]: 'Locale',
[Service.Storage]: 'Storage',

View File

@@ -2,6 +2,9 @@ import { OpenAPIV3 } from 'openapi-types';
import { Platform, type Service } from './references';
type SDKMethod = {
'rate-limit': number;
'rate-time': number;
'rate-key': string;
id: string;
title: string;
description: string;
@@ -293,7 +296,10 @@ export async function getService(
parameters: parameters ?? [],
responses: responses ?? [],
method,
url
url,
'rate-limit': operation['x-appwrite']['rate-limit'],
'rate-time': operation['x-appwrite']['rate-time'],
'rate-key': operation['x-appwrite']['rate-key']
});
}

View File

@@ -2,6 +2,7 @@
import { setContext } from 'svelte';
export let href: string;
export let icon = '';
export let title: string;
setContext('no-paragraph', true);
@@ -9,9 +10,17 @@
<li>
<a {href} class="aw-card is-normal" style:margin-block-end="0">
<header class="u-flex u-cross-baseline u-gap-4">
{#if icon}
<span
class="{icon} aw-u-font-size-24"
aria-hidden="true"
/>
{/if}
<h4 class="aw-sub-body-500 aw-u-color-text-primary">
{title}
</h4>
</header>
<p class="aw-sub-body-400 u-margin-block-start-4" style:margin-block="0">
<slot />
</p>

View File

@@ -12,9 +12,11 @@ Password dictionary can be enabled in the Auth service's **Security** tab on the
# Password hashing {% #password-hashing %}
Appwrite protects passwords by using the [Argon2](https://github.com/P-H-C/phc-winner-argon2) password-hashing algorithm.
Argon 2 is a resilient and secure password hashing algorithm, which is also the winner of the [Password Hashing Competition](https://www.password-hashing.net/)
Argon 2 is a resilient and secure password hashing algorithm, which is also the winner of the [Password Hashing Competition](https://www.password-hashing.net/).
Appwrite combines Argon 2 with the use of techniques such as salting, adjustable work factors, and memory hardness to securely handle passwords.
If an user is imported into Appwrite with hash differnt than Argon2, the password will be re-hashed on first successful user's sign in. This ensures all passwords are stored as securely as possible.
# Personal data {% #personal-data %}
Encourage passwords that are hard to guess by disallowing users to pick passwords that contain personal data.

View File

@@ -107,7 +107,7 @@ const client = //...
const Teams = new Teams(client);
const promise = Teams.create('[Team_ID]', '[NAME]');
const promise = Teams.create('<TEAM_ID>', '[NAME]');
```
## Labels
@@ -124,7 +124,7 @@ const client = //...
const users = new sdk.Users(client);
const promise = users.updateLabels('[USER_ID]', ['subscriber']);
const promise = users.updateLabels('<USER_ID>', ['subscriber']);
```
### Resources

View File

@@ -53,12 +53,18 @@
icon: 'icon-lightning-bolt',
isParent: true
},
{
label: 'Messaging',
href: '/docs/products/messaging',
icon: 'icon-send',
isParent: true
},
{
label: 'Storage',
href: '/docs/products/storage',
icon: 'icon-folder',
isParent: true
}
},
]
},
{

View File

@@ -68,6 +68,6 @@ Configure custom domains and customize communication templates.
Add a custom domain for your Appwrite APIs.
{% /cards_item %}
{% cards_item href="/docs/advanced/platform/message-templates" title="Message templates" %}
Create custom branding and messages when you communicate with users..
Create custom branding and messages when you communicate with users.
{% /cards_item %}
{% /cards %}

View File

@@ -49,6 +49,10 @@
label: 'Encryption',
href: '/docs/advanced/security/encryption'
},
{
label: '2-Factor authentication',
href: '/docs/advanced/security/mfa'
},
{
label: 'HTTPS',
href: '/docs/advanced/security/https'

View File

@@ -0,0 +1,36 @@
---
layout: article
title: Multi-factor Authentication
description: Appwrite helps you secure your developer accounts with MFA (multifactor authentication).
---
Multi-factor authentication (MFA) adds multiple layers of authentication to your Appwrite account,
which means a malicious actor cannot gain access to your accounts, even if one of the factors is compromised.
Appwrite currently supports MFA using TOTP (Time-based One-Time Password) with an authenticator app.
More factors of authentication will be added in the future.
{% info title="Looking to add MFA to your app?" %}
This page covers MFA for your Appwrite Console account.
If you're looking to add MFA to your app, follow the [Multi-factor authentication journey](/docs/products/auth/mfa).
{% /info %}
# Enable MFA {% #enable-mfa %}
To enable MFA on your Appwrite account, navigate to your Appwrite Console > your account menu on the top right > **Your account** > **Multi-factor authentication**.
{% only_dark %}
![Multi-factor authentication settings](/images/docs/advanced/security/dark/mfa.png)
{% /only_dark %}
{% only_light %}
![Multi-factor authentication settings](/images/docs/advanced/security/mfa.png)
{% /only_light %}
Toggle **Multi-factor authentication** to enable MFA for your account, then click **Add authentication factor**.
{% only_dark %}
![Multi-factor authentication modal](/images/docs/advanced/security/dark/mfa-modal.png)
{% /only_dark %}
{% only_light %}
![Multi-factor authentication modal](/images/docs/advanced/security/mfa-modal.png)
{% /only_light %}
Scan the QR code with your authenticator app, then enter the code from your authenticator app to verify the setup.
Make sure to save the recovery codes in a safe place, as they are the only way to access your account if you lose access to your authenticator app.

View File

@@ -106,8 +106,8 @@ If no errors occur, the array will not be present in the response.
# Authentication {% #authentication %}
GraphQL authenticates using Appwrite accounts and sessions.
Both accounts and sessions can be created with GraphQL using the `accountCreate`, `accountCreateEmailSession`,
`accountCreateAnonymousSession`, or `accountCreatePhoneSession` mutations.
Both accounts and sessions can be created with GraphQL using the `accountCreate`, `accountCreateEmailPasswordSession`,
`accountCreateAnonymousSession`, or `accountCreatePhoneToken` mutations.
More information and examples of authenticating users can be found in the dedicated [authentication guide](/docs/products/auth).
@@ -234,7 +234,7 @@ import { Client, Graphql } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your Appwrite Endpoint
.setProject('[PROJECT_ID]'); // Your project ID
.setProject('<PROJECT_ID>'); // Your project ID
const graphql = new Graphql(client);
@@ -271,7 +271,7 @@ import 'package:appwrite/appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your Appwrite Endpoint
.setProject('[PROJECT_ID]'); // Your project ID
.setProject('<PROJECT_ID>'); // Your project ID
final graphql = Graphql(client);
@@ -309,7 +309,7 @@ import io.appwrite.services.Graphql
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("[PROJECT_ID]") // Your project ID
.setProject("<PROJECT_ID>") // Your project ID
val graphql = Graphql(client)
@@ -346,7 +346,7 @@ import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("[PROJECT_ID]") // Your project ID
.setProject("<PROJECT_ID>") // Your project ID
let graphql = Graphql(client)

View File

@@ -16,7 +16,7 @@ import { Client } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
// Subscribe to files channel
client.subscribe('files', response => {
@@ -32,7 +32,7 @@ import 'package:appwrite/appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
final realtime = Realtime(client);
@@ -53,7 +53,7 @@ import AppwriteModels
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[PROJECT_ID]")
.setProject("<PROJECT_ID>")
let realtime = Realtime(client)
@@ -72,7 +72,7 @@ import io.appwrite.services.Realtime
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[PROJECT_ID]")
.setProject("<PROJECT_ID>")
val realtime = Realtime(client)
@@ -118,7 +118,7 @@ import { Client } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
client.subscribe('account', response => {
// Callback will be executed on all account events.
@@ -131,7 +131,7 @@ import 'package:appwrite/appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
final realtime = Realtime(client);
@@ -149,7 +149,7 @@ import AppwriteModels
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[PROJECT_ID]")
.setProject("<PROJECT_ID>")
let realtime = Realtime(client)
@@ -165,7 +165,7 @@ import io.appwrite.services.Realtime
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[PROJECT_ID]")
.setProject("<PROJECT_ID>")
val realtime = Realtime(client)
@@ -189,7 +189,7 @@ import { Client } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
client.subscribe(['collections.A.documents.A', 'files'], response => {
// Callback will be executed on changes for documents A and all files.
@@ -202,7 +202,7 @@ import 'package:appwrite/appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
final realtime = Realtime(client);
@@ -220,7 +220,7 @@ import AppwriteModels
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[PROJECT_ID]")
.setProject("<PROJECT_ID>")
let realtime = Realtime(client)
@@ -236,7 +236,7 @@ import io.appwrite.services.Realtime
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[PROJECT_ID]")
.setProject("<PROJECT_ID>")
val realtime = Realtime(client)
realtime.subscribe("databases.A.collections.A.documents.A", "files") {
@@ -257,7 +257,7 @@ import { Client } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
const unsubscribe = client.subscribe('files', response => {
// Callback will be executed on changes for all files.
@@ -273,7 +273,7 @@ import 'package:appwrite/appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
final realtime = Realtime(client);
@@ -309,7 +309,7 @@ import io.appwrite.services.Realtime
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[PROJECT_ID]")
.setProject("<PROJECT_ID>")
val realtime = Realtime(client)

View File

@@ -43,6 +43,10 @@
{
label: 'Security',
href: '/docs/products/auth/security'
},
{
label: 'Tokens',
href: '/docs/products/auth/tokens'
}
]
},
@@ -61,6 +65,10 @@
label: 'Magic URL login',
href: '/docs/products/auth/magic-url'
},
{
label: 'Email OTP login',
href: '/docs/products/auth/email-otp'
},
{
label: 'OAuth2 login',
href: '/docs/products/auth/oauth2'
@@ -73,6 +81,18 @@
label: 'JWT login',
href: '/docs/products/auth/jwt'
},
{
label: 'SSR login',
href: '/docs/products/auth/server-side-rendering'
},
{
label: 'Custom token login',
href: '/docs/products/auth/custom-token'
},
{
label: 'Multi-factor authentication',
href: '/docs/products/auth/mfa'
}
]
},
{
@@ -91,7 +111,7 @@
href: '/docs/references/cloud/client-web/teams'
}
]
},
}
];
</script>

View File

@@ -12,17 +12,19 @@ Each user's account can also have their own preference object, which you can use
# Signup and login {% #signup-login %}
You can signup and login a user with an account create through
[email password](/docs/products/auth/email-password),
[phone (SMS)](/docs/products/auth/phone-sms),
[Anonymous](/docs/products/auth/anonymous),
[magic URL](/docs/products/auth/magic-url), and
[OAuth 2](/docs/products/auth/oauth2)
authentication.
You can signup and login a user with an account created through
[Email and password](/docs/products/auth/email-password),
[OAuth2](/docs/products/auth/oauth2),
[Magic URL](/docs/products/auth/magic-url),
[Email OTP](/docs/products/auth/email-otp),
[Phone (SMS)](/docs/products/auth/phone-sms),
and [Anonymous](/docs/products/auth/anonymous) authentications.
You can also use [Custom token](/docs/products/auth/custom-token) to implement your own authentication flow, or integrate with any external provider.
# Preferences {% #preferences %}
You can store user preferences on a user's account using Appwrite's [Update Preferences](/docs/references/cloud/client-web/account#updatePrefs) endpoint. You can store preferences such as theme, notification settings, or preferred language so they can be synced across multiple devices.
You can store user preferences on a user's account using Appwrite's [Update preferences](/docs/references/cloud/client-web/account#updatePrefs) endpoint. You can store preferences such as theme, notification settings, or preferred language so they can be synced across multiple devices.
Preferences are stored as a key-value JSON object. The maximum allowed size for preferences is 64kB, and an error will be thrown if this limit is exceeded.
@@ -108,7 +110,7 @@ mutation {
```
{% /multicode %}
After a user's preferences are updated, they can be retrieved using the [get account preferences](/docs/references/cloud/client-web/account#getPrefs) endpoint.
After a user's preferences are updated, they can be retrieved using the [Get preferences](/docs/references/cloud/client-web/account#getPrefs) endpoint.
{% multicode %}
```js

View File

@@ -10,7 +10,7 @@ Anonymous sessions allow you to implement **guest** users. Guest users let you s
# Create anonymous session {% #createSession %}
Create an anonymous session with [Create Anonymous Session](/docs/references/cloud/client-web/account#createAnonymousSession) route.
Create an anonymous session with [Create Anonymous Session](/docs/references/cloud/client-web/account#createAnonymousSession) endpoint.
{% multicode %}
```js
@@ -78,7 +78,7 @@ mutation {
# Attaching an account {% #attach-account %}
Anonymous users cannot sign back in. If the session expires, they move to another computer, or they clear their browser data, they won't be able to log in again. Remember to prompt the user to create an account to not lose their data.
Anonymous users cannot sign back in. If the session expires, they move to another computer, or they clear their browser data, they won't be able to log in again. Remember to prompt the user to claim an account to not lose their data.
Create an account with any of these methods to transition from an anonymous session to a user account session.

View File

@@ -0,0 +1,239 @@
---
layout: article
title: Custom token login
description: Limitless authentication flow in Appwrite. Find out how to implement custom authentication flow or connect to 3rd party authentication providers.
---
Tokens are short-lived secrets created by an [Appwrite Server SDK](/docs/sdks#server) that can be exchanged for session by a [Client SDK](/docs/sdks#client) to log in users. You may already be familiar with tokens if you checked out [Magic URL login](/docs/products/auth/magic-url), [Email OTP login](/docs/products/auth/email-otp) or [Phone (SMS) login](/docs/products/auth/phone-sms).
Custom token allows you to use [Server SDK](/docs/sdks#server) to generate tokens for your own implementations. This allows you to code your own authentication methods using Appwrite Functions or your own backend. You could implement username and password sign-in, captcha-protected authentication, phone call auth, and much more. Custom tokens also allow you to skip authentication which is useful when you integrate Appwrite with external authenticaion providers such as Auth0, TypingDNA, or any provider trusted by your users.
# Create custom token {% #create-custom-token %}
Once you have your server endpoint prepared either in an Appwrite Function or a server integration, you can use the [Create token](/docs/references/cloud/server-nodejs/users#/docs/references/cloud/server-nodejs/users#createToken) endpoint of the [Users API](/docs/products/auth/users) to generate a token.
{% multicode %}
```js
import { Client, Users } from "node-appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>'); // Your project ID
.setKey('<API_KEY>'); // Your project API key
const users = new Users(client);
const token = await users.createToken('[USER_ID]');
const secret = token.secret;
```
```php
use Appwrite\Client;
use Appwrite\Users;
$client = (new Client())
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<PROJECT_ID>') // Your project ID
->setKey('<API_KEY>'); // Your project API key
$users = new Users($client);
$token = $users->createToken('[USER_ID]');
$secret = $token['secret'];
```
```python
from appwrite.client import Client
from appwrite.users import Users
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your project API key
)
users = Users(client)
token = users.create_token('[USER_ID]')
secret = token.secret
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your project API key
users = Users.new(client)
token = users.create_token('[USER_ID]')
secret = token['secret']
```
```deno
import { Client, Users } from "https://deno.land/x/appwrite/mod.ts";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>'); // Your project API key
const users = new Users(client);
const token = await users.createToken('[USER_ID]');
const secret = token.secret;
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>'); // Your project API key
final users = Users(client);
final token = await users.createToken('[USER_ID]');
final secret = token.secret;
```
```kotlin
import io.appwrite.Client
import io.appwrite.Users
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your project API key
val users = Users(client)
val token = users.createToken("[USER_ID]")
val secret = token.secret
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your project API key
let users = Users(client)
let token = try await users.createToken("[USER_ID]")
let secret = token.secret
```
```csharp
using Appwrite;
var client = new Client()
.SetEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<PROJECT_ID>") // Your project ID
.SetKey("<API_KEY>"); // Your project API key
var users = new Users(client);
var token = await users.CreateToken("[USER_ID]");
var secret = token.secret;
```
{% /multicode %}
The newly created token includes a `secret` which is 6 character long hexadecimal string. You can configure length of the secret and expiry when creating a token.
If you are integrating with external authentication providers or implementing your own authentication, make sure to validate user authenticated properly before generating a token for them.
If you are implementing token-based authentication flow, share the token secret with user over any channel of your choice instead of directly giving it to him in the response.
If the client doesn't know the user's ID during authentication, we recommend to directly return user ID to the client as part of this step. If necessary, you can check if the user with an user ID exists first, and create a new user if needed.
# Login {% #login %}
Once the client receives a token secret, we can use it to authenticate the user in the application. Use the [Client SDK's](/docs/sdks#client) [Create session endpoint](/docs/references/cloud/server-nodejs/account#createSession) to exchange the token secret for a valid session, which logs the user.
{% multicode %}
```js
import { Client, Account } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('<PROJECT_ID>');
const account = new Account(client);
const session = await account.createSession(
'[USER_ID]',
'[SECRET]'
);
```
```dart
import 'package:appwrite/appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('<PROJECT_ID>');
final account = Account(client);
final session = await account.createSession(
userId: '[USER_ID]',
secret: '[SECRET]'
);
```
```kotlin
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("<PROJECT_ID>");
val account = Account(client);
val session = account.createSession(
userId = "[USER_ID]",
secret = "[SECRET]"
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("<PROJECT_ID>");
let account = Account(client);
let session = try await account.createSession(
userId: "[USER_ID]",
secret: "[SECRET]"
);
```
```graphql
mutation {
accountcreateSession(userId: "[USER_ID]", secret: "[SECRET]") {
_id
userId
provider
expire
}
}
```
{% /multicode %}
When the session is successfully created, the session is stored in a persistent manner and you can now do requests as authorized user from the application.

View File

@@ -0,0 +1,243 @@
---
layout: article
title: Email OTP
description: Seamless sign in with Email OTP authentication in Appwrite. Learn how to provide simple and secure passwordless user accounts.
---
Email OTP (one-time password) authentication lets users create accounts using their email address and log in using a 6 digit code delivered to their email inbox. This method is similar to [Magic URL login](/docs/products/auth/magic-url), but can provide better user experience in some scenarios.
{% info title="Email OTP vs Magic URL" %}
Email OTP sends an email with a 6 digit code that user needs to enter into the app, while Magic URL delivers a clickable button or a link to user's inbox.
Both allow passwordless login flows with different advantages.
| Benefits of Email OTP | Downsides of Email OTP |
|--------------------------------------------------------------------|------------------------------------------|
| Doesn't require user to be signed into email inbox on the device | Expires quicker |
| Doesn't disturb application flow with a redirect | Requires more inputs from user |
| Doesn't require deep linking on mobile apps | |
{% /info %}
# Send email {% #send-email %}
Email OTP authentication is done using a two-step authentication process. The authentication request is initiated from the client application and an email message is sent to the user's email inbox. The email will contain a 6-digit number the user can use to log in.
Send an an email to initiate the authentication process. A **new account** will be created for this email if it has never been used before.
{% multicode %}
```js
import { Client, Account, ID } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('<PROJECT_ID>');
const account = new Account(client);
const sessionToken = await account.createEmailToken(
ID.unique(),
'email@example.com'
);
const userId = sessionToken.userId;
```
```dart
import 'package:appwrite/appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('<PROJECT_ID>');
final account = Account(client);
final sessionToken = await account.createEmailToken(
userId: ID.unique(),
email: 'email@example.com'
);
final userId = sessionToken.userId;
```
```kotlin
import io.appwrite.Client
import io.appwrite.services.Account
import io.appwrite.ID
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("<PROJECT_ID>");
val account = Account(client);
val sessionToken = account.createEmailToken(
userId = ID.unique(),
email = "email@example.com"
);
val userId = sessionToken.userId;
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("<PROJECT_ID>");
let account = Account(client);
let sessionToken = try await account.createEmailToken(
userId: ID.unique(),
email: "email@example.com"
);
let userId = sessionToken.userId;
```
```graphql
mutation {
accountCreateEmailToken(userId: "unique()", email: "email@example.com") {
_id
userId
secret
expire
}
}
```
{% /multicode %}
# Login {% #login %}
After initiating the email OTP authentication process, the returned user ID and secret are used to authenticate the user. The user will use their 6-digit one-time password to log in to your app.
{% multicode %}
```js
import { Client, Account, ID } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('<PROJECT_ID>');
const account = new Account(client);
const session = await account.createSession(
userId,
'[SECRET]'
);
```
```dart
import 'package:appwrite/appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('<PROJECT_ID>');
final account = Account(client);
final session = await account.createSession(
userId: userId,
secret: '[SECRET]'
);
```
```kotlin
import io.appwrite.Client
import io.appwrite.services.Account
import io.appwrite.ID
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("<PROJECT_ID>");
val account = Account(client);
val session = account.createSession(
userId = userId,
secret = "[SECRET]"
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("<PROJECT_ID>");
let account = Account(client);
let session = try await account.createSession(
userId: userId,
secret: "[SECRET]"
);
```
```graphql
mutation {
accountcreateSession(userId: "<USER_ID>", secret: "[SECRET]") {
_id
userId
provider
expire
}
}
```
{% /multicode %}
After the secret is verified, a session will be created.
# Security phrase {% #security-phrase %}
A security phrase is a randomly generated phrase provided on the login page, as well as inside Email OTP login email. Users must match the phrase on the login page with the phrase provided inside the email. Security phrases offer protection for various types of phishing and man-in-the-middle attacks.
By default, security phrases are disabled. To enable a security phrase in Email OTP, enable it in first step of the authentication flow.
{% multicode %}
```js
import { Client, Account, ID } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>'); // Your project ID
const account = new Account(client);
const promise = account.createEmailToken(
ID.unique(),
'email@example.com',
true
);
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});
```
```graphql
mutation {
accountCreateEmailToken(
userId: "ID.unique()",
email: "email@example.com",
phrase: true
) {
_id
_createdAt
userId
secret
expire
phrase
}
}
```
{% /multicode %}
By enabling security phrase feature, you will recieve `phrase` in the response. You need to display this phrase to the user, and we recommend informing user what this phrase is and how to check it. When security phrase is enabled, email will also include a new section providing user with the security phrase.

View File

@@ -8,7 +8,7 @@ Email and password login is the most commonly used authentication method. Appwri
# Signup {% #sign-up %}
You can use the Appwrite Client SDKs to create an account using email and password.
You can use the Appwrite [Client SDKs](/docs/sdks#client) to create an account using email and password.
```js
import { Client, Account, ID } from "appwrite";
@@ -19,7 +19,7 @@ const client = new Client()
const account = new Account(client);
const promise = account.create('[USER_ID]', 'email@example.com', '');
const promise = account.create(ID.unique(), 'email@example.com', 'password');
promise.then(function (response) {
console.log(response); // Success
@@ -30,9 +30,31 @@ promise.then(function (response) {
Passwords are hashed with [Argon2](https://github.com/P-H-C/phc-winner-argon2), a resilient and secure password hashing algorithm.
# Login {% #login %}
After you've created your account, users can be logged in using the [Create Email Password Session](/docs/references/cloud/server-nodejs/account#createEmailPasswordSession) endpoint.
```js
import { Client, Account } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>'); // Your project ID
const account = new Account(client);
const promise = account.createEmailPasswordSession('email@example.com', 'password');
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});
```
# Verification {% #verification %}
After an account is created, it can be verified through the account create verification route. The user doesn't need to be verified to log in, but you can restrict resource access to verified users only using permissions through the `user([USER_ID], "verified")` role.
After an account is created, it can be verified through the account create verification endpoint. The user doesn't need to be verified to log in, but you can restrict resource access to verified users only using permissions through the `user([USER_ID], "verified")` role.
First, send a verification email. Specify a redirect URL which users will be redirected to. The verification secrets will be appended as query parameters to the redirect URL. In this example, the redirect URL is `https://example.com/verify`.
@@ -41,11 +63,11 @@ import { Client, Account } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setProject('<PROJECT_ID>') // Your project ID
const account = new Account(client);
const promise = account.createVerification('https://example.com');
const promise = account.createVerification('https://example.com/verify');
promise.then(function (response) {
console.log(response);
@@ -56,7 +78,7 @@ promise.then(function (response) {
Next, implement the verification page in your app. This page will parse the secrets passed in through the `userId` and `secret` query parameters. In this example, the code below will be found in the page served at `https://example.com/verify`.
Since the secrets are passed in through url params, it will be easiest to perform this step in the browser.
Since the secrets are passed in through query params, it will be easiest to perform this step in the browser.
```js
import { Client, Account } from "appwrite";
@@ -80,31 +102,9 @@ promise.then(function (response) {
});
```
# Login {% #login %}
After you've created your account, users can be logged in using the Create Email Session route.
```js
import { Client, Account } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>'); // Your project ID
const account = new Account(client);
const promise = account.createEmailSession('email@example.com', 'password');
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});
```
# Password Recovery {% #password-recovery %}
If a user forgets their password, they can initiate a password recovery flow to recover their password. The Create Password Recovery endpoint sends the user an email with a temporary secret key for password reset. When the user clicks the confirmation link, they are redirected back to the password reset URL with the secret key and email address values attached to the URL as query strings.
If a user forgets their password, they can initiate a password recovery flow to recover their password. The Create Password Recovery endpoint sends the user an email with a temporary secret key for password reset. When the user clicks the confirmation link, they are redirected back to the password reset URL with the secret key and user ID values attached to the URL as query strings.
Only redirect URLs to domains added as a platform on your Appwrite Console will be accepted. URLs not added as a platform are rejected to protect against redirect attacks.
@@ -115,7 +115,7 @@ const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>'); // Your project ID
const promise = account.createRecovery('email@example.com', 'https://example.com');
const promise = account.createRecovery('email@example.com', 'https://example.com/recover-password');
promise.then(function (response) {
console.log(response); // Success
@@ -133,11 +133,15 @@ const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>'); // Your project ID
const urlParams = new URLSearchParams(window.location.search);
const secret = urlParams.get('secret');
const userId = urlParams.get('userId');
const promise = account.updateRecovery(
'[USER_ID]',
'[SECRET]',
'password',
'password'
userId,
secret,
'new-password',
'new-password'
);
promise.then(function (response) {
@@ -149,4 +153,4 @@ promise.then(function (response) {
# Security {% #security %}
Appwrite's security first mindset goes beyond a securely implemented of authentication API. You can enable features like password dictionary, password history, and disallow personal data in passwords to encourage users to pick better passwords. By enabling these features, you protect user data and teach better password choices, which helps make the internet a safer place.
Appwrite's security first mindset goes beyond a securely implemented of [Authentication API](/docs/references/cloud/client-web/account). You can enable features like password dictionary, password history, and disallow personal data in passwords to encourage users to pick better passwords. By enabling these features, you protect user data and teach better password choices, which helps make the internet a safer place. [Learn more about security features](/docs/products/auth/security).

View File

@@ -18,7 +18,7 @@ When you build backend APIs to extend Appwrite's functionality, these APIs shoul
[JSON Web Tokens](https://jwt.io/introduction) (JWTs) are a secure means to transfer information or claims between two parties. JWTs act like temporary copies of the user's ID card that allow Appwrite's Server SDKs to access information on behalf of a user.
You need to create a session using the Client SDKs **before** generating a JWT. The JWT will be a stateless proof of claim for the identity of the authenticated user and expire after 15 minutes or when the session is deleted.
You need to create a session using the [Client SDKs](/docs/sdks#client) **before** generating a JWT. The JWT will be a stateless proof of claim for the identity of the authenticated user and expire after 15 minutes or when the session is deleted.
You can generate a JWT like this on a [Client SDK](/docs/sdks#client).
@@ -374,7 +374,7 @@ const { Client } = require('node-appwrite');
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('98fd4...a2ad2'); // Your secret API key
.setKey('<API_KEY>'); // Your secret API key
const databases = new sdk.Databases(client);
@@ -391,7 +391,7 @@ use Appwrite\Client;
$client = (new Client())
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<PROJECT_ID>') // Your project ID
->setKey('98fd4...a2ad2'); // Your secret API key
->setKey('<API_KEY>'); // Your secret API key
$databases = new Databases($client);
@@ -409,7 +409,7 @@ client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.set_project('<PROJECT_ID>') // Your project ID
.set_key('98fd4...a2ad2') // Your secret API key
.set_key('<API_KEY>') // Your secret API key
)
databases = Databases(client)
@@ -428,7 +428,7 @@ include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('98fd4...a2ad2') # Your secret API key
.set_key('<API_KEY>') # Your secret API key
databases = Databases.new(client)
@@ -444,7 +444,7 @@ import { Client } from "https://deno.land/x/appwrite/mod.ts";
let client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('98fd4...a2ad2'); // Your secret API key
.setKey('<API_KEY>'); // Your secret API key
let databases = new sdk.Databases(client);
@@ -460,7 +460,7 @@ import 'package:dart_appwrite/dart_appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('98fd4...a2ad2'); // Your secret API key
.setKey('<API_KEY>'); // Your secret API key
final databases = Databases(client);
@@ -476,7 +476,7 @@ import io.appwrite.Client
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey('98fd4...a2ad2'); // Your secret API key
.setKey('<API_KEY>'); // Your secret API key
val databases = Databases(client)
@@ -492,7 +492,7 @@ import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey('98fd4...a2ad2'); // Your secret API key
.setKey('<API_KEY>'); // Your secret API key
let databases = Databases(client)
@@ -510,7 +510,7 @@ using Appwrite.Models;
var client = new Client()
.SetEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<PROJECT_ID>") // Your project ID
.SetKey('98fd4...a2ad2'); // Your secret API key
.SetKey('<API_KEY>'); // Your secret API key
var databases = new Databases(client);

View File

@@ -12,13 +12,13 @@ const sdk = require('node-appwrite');
const client = new sdk.Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('98fd4...a2ad2'); // Your secret API key
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>'); // Your secret API key
const users = new sdk.Users(client);
const promise = users.updateLabels(
'[USER_ID]',
'<USER_ID>',
[ 'subscriber' ]
);
@@ -38,13 +38,13 @@ $client = new Client();
$client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('98fd4...a2ad2'); // Your secret API key
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>'); // Your secret API key
$users = new Users($client);
$result = $users->updateLabels(
'[USER_ID]',
'<USER_ID>',
[ 'subscriber' ]
);
```
@@ -58,14 +58,14 @@ client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('98fd4...a2ad2') # Your secret API key
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
)
users = Users(client)
result = users.update_labels(
'[USER_ID]',
'<USER_ID>',
[ 'subscriber' ]
);
```
@@ -76,13 +76,13 @@ include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('98fd4...a2ad2') # Your secret API key
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
users = Users.new(client)
response = users.update_labels(
user_id: '[USER_ID]',
user_id: '<USER_ID>',
labels: [ 'subscriber' ]
);
```
@@ -92,13 +92,13 @@ import * as sdk from "https://deno.land/x/appwrite/mod.ts";
let client = new sdk.Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('98fd4...a2ad2'); // Your secret API key
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>'); // Your secret API key
let users = new sdk.Users(client);
const promise = users.updateLabels(
'[USER_ID]',
'<USER_ID>',
[ 'subscriber' ]
);
@@ -113,13 +113,13 @@ import 'package:dart_appwrite/dart_appwrite.dart';
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('98fd4...a2ad2'); // Your secret API key
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>'); // Your secret API key
final users = Users(client);
final result = await users.updateLabels(
userId: '[USER_ID]',
userId: '<USER_ID>',
labels: [ 'subscriber' ],
);
```
@@ -130,13 +130,13 @@ import io.appwrite.services.Users
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("98fd4...a2ad2") // Your secret API key
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
val users = Users(client)
val response = users.updateLabels(
userId = "[USER_ID]",
userId = "<USER_ID>",
labels = [ 'subscriber' ]
);
```
@@ -146,13 +146,13 @@ import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("98fd4...a2ad2") // Your secret API key
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
let users = Users(client)
let response = try await users.updateLabels(
userId: "[USER_ID]",
userId: "<USER_ID>",
labels: [ 'subscriber' ]
);
```
@@ -162,13 +162,13 @@ using Appwrite;
var client = new Client()
.SetEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("98fd4...a2ad2"); // Your secret API key
.SetProject("<PROJECT_ID>") // Your project ID
.SetKey("<API_KEY>"); // Your secret API key
var users = new Users(client);
var response = await users.UpdateLabels(
userId: "[USER_ID]",
userId: "<USER_ID>",
labels: [ 'subscriber' ]
);
```

View File

@@ -1,14 +1,26 @@
---
layout: article
title: Magic URL login
description: Add magic URL to your authentication in Appwrite. Explore the convenience of passwordless login and email-based authentication using magic links."
description: Add magic URL to your authentication in Appwrite. Explore the convenience of passwordless login and email-based authentication using magic links.
---
Magic URL is a password-less way to authenticate users. When a user logs in by providing their email, they will receive an email with a "magic" link that contains a secret used to log in the user. The user can simply click the link to be logged in.
Magic URL is a password-less way to authenticate users. When a user logs in by providing their email, they will receive an email with a "magic" link that contains a secret used to log in the user. The user can simply click the link to be logged in. This method is similar to [Email OTP login](/docs/products/auth/email-otp), but can provide quicker sign-in in some scenarios.
{% info title="Magic URL vs Email OTP" %}
Magic URL delivers a clickable button or a link to user's inbox, while Email OTP sends email with 6 digit code that user needs to enter into the app.
Both allow passwordless login flows with different advantages.
| Benefits of Magic URL | Downsides of Magic URL |
|----------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|
| Doesn't expire too quickly while remaining secure | Requires user to be signed into email inbox on the device |
| Doesn't require many inputs, only 1 click | Disturbs application flow with a redirect |
| | Requires deep linking when developing PWA or mobile apps |
{% /info %}
# Send email {% #init %}
Initialize the log in process with the [Create Magic URL Session](/docs/references/cloud/client-web/account#createMagicURLSession) route. If the email has never been used, a **new account is generated**, then the user will receive an email. If the email is already attached to an account, the **user ID is ignored** and the user will receive a link in their email.
Initialize the log in process with the [Create Magic URL Token](/docs/references/cloud/client-web/account#createMagicURLToken) endpoint. If the email has never been used, a **new account is generated**, then the user will receive an email. If the email is already attached to an account, the **user ID is ignored** and the user will receive a link in their email.
{% multicode %}
```js
@@ -20,7 +32,7 @@ const client = new Client()
const account = new Account(client);
const promise = account.createMagicURLSession(ID.unique(), 'email@example.com');
const promise = account.createMagicURLToken(ID.unique(), 'email@example.com');
promise.then(function (response) {
console.log(response); // Success
@@ -31,7 +43,7 @@ promise.then(function (response) {
```graphql
mutation {
accountCreateMagicURLSession(
accountCreateMagicURLToken(
userId: "ID.unique()",
email: "email@example.com"
) {
@@ -65,12 +77,12 @@ const urlParams = new URLSearchParams(window.location.search);
const secret = urlParams.get('secret');
const userId = urlParams.get('userId');
const user = await account.updateMagicURLSession(userId, secret);
const user = await account.createSession(userId, secret);
```
```graphql
mutation {
accountUpdateMagicURLSession(
accountCreateSession(
userId: "unique()",
secret: "[SECRET]"
) {
@@ -83,3 +95,50 @@ mutation {
}
```
{% /multicode %}
# Security phrase {% #security-phrase %}
A security phrase is a randomly generated phrase provided on the login page, as well as inside Magic URL login email. Users must match the phrase on the login page with the phrase provided inside the email. Security phrases offer protection for various types of phishing and man-in-the-middle attacks.
By default, security phrases are disabled. To enable a security phrase in Magic URL, enable it in first step of the authentication flow.
{% multicode %}
```js
import { Client, Account, ID } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>'); // Your project ID
const account = new Account(client);
const promise = account.createMagicURLToken(ID.unique(), 'email@example.com', true);
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
});
```
```graphql
mutation {
accountCreateMagicURLToken(
userId: "ID.unique()",
email: "email@example.com",
phrase: true
) {
_id
_createdAt
userId
secret
expire
phrase
}
}
```
{% /multicode %}
By enabling security phrase feature, you will recieve `phrase` in the response. You need to display this phrase to the user, and we recommend informing user what this phrase is and how to check it. When security phrase is enabled, email will also include a new section providing user with the security phrase.

View File

@@ -0,0 +1,546 @@
---
layout: article
title: 2-Factor authentication
description: Add multiple layers of authentication to your applications powered by Appwrite Authentication.
---
Two-factor authentication (2FA) greatly increases the security of your apps by adding additional layers of protection.
When 2FA is enabled, a malicious actor needs to compromise multiple authentication factors to gain unauthorized access.
Appwrite Authentication lets you easily implement 2FA in your apps, letting you build more securely and quickly.
{% info title="Looking for 2FA on your Console account?" %}
This page covers 2FA for your app's end-users.
If you are looking for 2FA on your Appwrite Console account, please refer to the [Console 2FA page](/docs/advanced/security/mfa).
{% /info %}
Appwrite currently allows two factors of authentication. More factors of authentication will be available soon.
Here are the steps to implement 2FA in your application.
{% section #enable-2fa step=1 title="Enable 2FA on an account" %}
You can enable 2FA on your account by calling `account.updateMFA()`.
You will need to have added more than 1 factors of authentication to an account before
the 2FA is enforced.
Initialize your Appwrite SDK's `Client` and `Account`.
{% multicode %}
```js
import { Client, Account } from "appwrite";
const client = new Client();
const account = new Account(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
;
```
```dart
import 'package:appwrite/appwrite.dart';
void main() { // Init SDK
Client client = Client();
Account account = Account(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
;
}
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
let account = Account(client)
```
```kotlin
import io.appwrite.Client
import io.appwrite.services.Account
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
val account = Account(client)
```
{% /multicode %}
{% multicode %}
```js
const result = await account.updateMFA(true);
```
```dart
Future result = account.updateMFA(
mfa: false,
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
```
```swift
let user = try await account.updateMFA(
mfa: xfalse
)
```
```kotlin
val response = account.updateMFA(
mfa = false
)
```
{% /multicode %}
{% /section %}
{% section #init-login step=2 title="Initialize login" %}
Begin your login flow with the default authentication method used by your app, for example, email password.
{% multicode %}
```js
const session = await account.createEmailPasswordSession(
'email@example.com', // email
'password' // password
);
```
```dart // Init SDK
Future session = account.createEmailPasswordSession(
email: 'email@example.com',
password: 'password',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
```
```swift
let session = try await account.createEmailPasswordSession(
email: "email@example.com",
password: "password"
)
```
```kotlin
val session = account.createEmailPasswordSession(
email = "email@example.com",
password = "password"
)
```
{% /multicode %}
{% /section %}
{% section #check-for-2fa step=3 title="Check for multi-factor" %}
Upon successful login in the first authentication step, check the status of the login by calling `account.get()`.
If more than one factors are required, you will the error `user_more_factors_required`. Redirect the user in your app to
perform the MFA challenge.
{% multicode %}
```js
try {
const response = await account.get();
console.log(response);
} catch (error) {
console.log(error);
if (error.type === `user_more_factors_required`){
// redirect to perform MFA
}
else {
// handle other errors
}
}
```
```dart
const promise = account.get();
promise.then(function (response) {
console.log(response); // Success
}, function (error) {
console.log(error); // Failure
if (error.type === "user_more_factors_required"){
// redirect to perform MFA
}
else {
// handle other errors
}
});
```
```dart
Future result = account.get();
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
if (error.type == 'user_more_factors_required') {
// redirect to perform MFA
} else {
// handle other errors
}
});
```
```swift
do {
let user = try await account.get()
} catch let error as AppwriteException {
print(error.message)
if error.type == "user_more_factors_required" {
// redirect to perform MFA
} else {
// handle other errors
}
}
```
```kotlin
try {
val response = account.get()
println(response)
} catch (error: AppwriteException) {
println(error.message)
if (error.type == "user_more_factors_required") {
// redirect to perform MFA
} else {
// handle other errors
}
}
```
{% /multicode %}
{% /section %}
{% section #list-provider step=4 title="List factors" %}
You can check which factors are enabled for an account using `account.listFactors()`.
The returned object will be formatted like this.
```js
{
totp: true, // time-based one-time password
email: false, // email
phone: true // phone
}
```
{% multicode %}
```js
const factors = await account.listFactors();
// redirect based on factors returned.
```
```dart
Future result = account.listFactors();
result
.then((response) {
print(response);
// redirect based on factors returned.
}).catchError((error) {
print(error.response);
});
```
```swift
let mfaFactors = try await account.listFactors()
// redirect based on factors returned.
```
```kotlin
val response = account.listFactors()
// redirect based on factors returned.
```
{% /multicode %}
{% /section %}
{% section #create-challenge step=5 title="Create challenge" %}
Based on the factors available, initialize an additional auth step.
Calling these methods will send a challenge to the user.
You will need to save the challenge ID to complete the challenge in a later step.
{% tabs %}
{% tabsitem #email title="Email" %}
Appwrite will use a verified email on the user's account to send the challenge code via email.
Note that this is only valid as a second factor if the user did not initialize their login with email OTP.
{% multicode %}
```js
const challenge = await account.createChallenge(
'email' // factor
);
// Save the challenge ID to complete the challenge later
const challengeId = challenge.$id;
```
```dart
Future result = account.createChallenge(
factor: 'email',
);
result
.then((response) {
print(response);
// Save the challenge ID to complete the challenge later
var challengeId = response.$id;
}).catchError((error) {
print(error.response);
});
```
```swift
let mfaChallenge = try await account.createChallenge(
factor: "email"
)
// Save the challenge ID to complete the challenge later
let challengeId = mfaChallenge.id
```
```kotlin
val response = account.createChallenge(
factor = "email"
)
// Save the challenge ID to complete the challenge later
val challengeId = response.id
```
{% /multicode %}
{% /tabsitem %}
{% tabsitem #phone title="Phone" %}
Appwrite will use a verified phone number on the user's account to send the challenge code via SMS.
You cannot use this method if the user initialized their login with phone OTP.
{% multicode %}
```js
const challenge = await account.createChallenge(
'phone' // factor
);
// Save the challenge ID to complete the challenge later
const challengeId = challenge.$id;
```
```dart
Future result = account.createChallenge(
factor: 'phone',
);
result
.then((response) {
print(response);
// Save the challenge ID to complete the challenge later
var challengeId = response.$id;
}).catchError((error) {
print(error.response);
});
```
```swift
let mfaChallenge = try await account.createChallenge(
factor: "phone"
)
// Save the challenge ID to complete the challenge later
let challengeId = mfaChallenge.id
```
```kotlin
val response = account.createChallenge(
factor = "phone"
)
// Save the challenge ID to complete the challenge later
val challengeId = response.id
```
{% /multicode %}
{% /tabsitem %}
{% tabsitem #totp title="TOTP" %}
Appwrite supports TOTP (Time-based One-Time Password) as a second factor.
This requires the user to have a TOTP authenticator app installed on their device.
To setup a TOTP authenticator, you can use the `account.addAuthenticator()` method.
{% multicode %}
```js
const { backups, secret, uri } = await account.addAuthenticator('totp');
```
```dart
Future result = account.addAuthenticator(
type: 'totp',
);
result
.then((response) {
print(response.backups);
print(response.secret);
print(response.uri);
}).catchError((error) {
print(error.response);
});
```
```swift
let response = try await account.addAuthenticator(
type: "totp"
)
let (backups, secret, uri) = (response.backups, response.secret, response.uri)
```
```kotlin
val response = account.addAuthenticator(
type = "totp"
)
val backups = response.backups
val secret = response.secret
val uri = response.uri
```
{% /multicode %}
After the user adds this authenticator to their app, you'll need to verify the setup succeeded by prompting the user to enter a code from their TOTP authenticator app.
The TOTP needs to be submitted like this.
{% multicode %}
```js
const { backups, secret, uri } = await account.verifyAuthenticator('totp', <TOTP_FROM_USER>);
```
```dart
Future result = account.verifyAuthenticator(
type: 'totp',
<TOTP_FROM_USER>
);
result
.then((response) {
print(response.backups);
print(response.secret);
print(response.uri);
}).catchError((error) {
print(error.response);
});
```
```swift
let response = try await account.verifyAuthenticator(
type: "totp",
<TOTP_FROM_USER>
)
let (backups, secret, uri) = (response.backups, response.secret, response.uri)
```
```kotlin
val response = account.verifyAuthenticator(
type = "totp",
<TOTP_FROM_USER>
)
val backups = response.backups
val secret = response.secret
val uri = response.uri
```
{% /multicode %}
You'll need to display the `uri` to the user as a QR code to scan with their TOTP authenticator app.
{% multicode %}
```js
const avatarts = new Avatars();
// display image at QRCode.href to your user
const QRCode = await avatarts.getQR(uri);
```
```dart
final avatars = Avatars();
// display image at QRCode.href to your user
final QRCode = await avatars.getQR(uri);
```
```swift
let avatars = Avatars()
// display image at QRCode.href to your user
let QRCode = try await avatars.getQR(uri)
```
```kotlin
val avatars = Avatars()
// display image at QRCode.href to your user
val QRCode = avatars.getQR(uri)
```
{% /multicode %}
If the user's unable to scan QR codes, you can display the `secret` to the user.
After adding the authenticator, you should also prompt the user to save their `backups`.
These backup code are the only way to recover access to their account if they lose access to their TOTP authenticator app.
Lastly, you can initialize the TOTP challenge.
{% multicode %}
```js
const challenge = await account.createChallenge(
'totp' // factor
);
// Save the challenge ID to complete the challenge later
const challengeId = challenge.$id;
```
```dart
Future result = account.createChallenge(
factor: 'totp',
);
result
.then((response) {
print(response);
// Save the challenge ID to complete the challenge later
var challengeId = response.$id;
}).catchError((error) {
print(error.response);
});
```
```swift
let mfaChallenge = try await account.createChallenge(
factor: "totp"
)
// Save the challenge ID to complete the challenge later
let challengeId = mfaChallenge.id
```
```kotlin
val response = account.createChallenge(
factor = "totp"
)
// Save the challenge ID to complete the challenge later
val challengeId = response.id
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}
{% section #complete-challenge step=6 title="Complete challenge" %}
Once the user receives the challenge code, you can pass the code back to Appwrite to complete the challenge.
{% multicode %}
```js
const response = await account.updateChallenge(
'<CHALLENGE_ID>', // challengeId
'<OTP>' // otp
);
```
```dart
Future result = account.updateChallenge(
challengeId: '<CHALLENGE_ID>',
otp: '<OTP>',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
```
```swift
val response = account.updateChallenge(
challengeId = "<CHALLENGE_ID>",
otp = "<OTP>"
)
```
```kotlin
let result = try await account.updateChallenge(
challengeId: "<CHALLENGE_ID>",
otp: "<OTP>"
)
```
{% /multicode %}
{% /section %}

View File

@@ -6,11 +6,11 @@ description: Integrate OAuth2 authentication seamlessly with Appwrite. Learn how
OAuth authentication allows users to log in using accounts from other popular services. This can be convenient for users because they can start using your app without creating a new account. It can also be more secure, because the user has one less password that could become vulnerable.
When using OAuth to authenticate, the authentication request is initiated from the client application. The user is then redirected to an OAuth 2 provider to complete the authentication step, and finally, the user is redirected back to the client application.
When using OAuth to authenticate, the authentication request is initiated from the client application. The user is then redirected to an OAuth2 provider to complete the authentication step, and finally, the user is redirected back to your application.
# Configure OAuth2 login {% #configure %}
Before using OAuth 2 login, you need to enable and configure an OAuth 2 login provider.
Before using OAuth2 login, you need to enable and configure an OAuth2 provider.
1. Navigate to your Appwrite project.
2. Navigate to **Auth** > **Settings**.
@@ -22,13 +22,12 @@ Before using OAuth 2 login, you need to enable and configure an OAuth 2 login pr
# Initialize OAuth2 login {% #init %}
To initialize the OAuth 2 login process, use the [Create OAuth 2 Session](/docs/references/cloud/client-web/account#createOAuth2Session) route.
To initialize the OAuth2 login process, use the [Create OAuth2 Session](/docs/references/cloud/client-web/account#createOAuth2Session) endpoint.
{% tabs %}
{% tabsitem #js title="Javascript" %}
```js
// Web SDK
import { Client, Account } from "appwrite";
import { Client, Account, OAuthProvider } from "appwrite";
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
@@ -37,13 +36,25 @@ const client = new Client()
const account = new Account(client);
// Go to OAuth provider login page
account.createOAuth2Session('amazon', [LINK_ON_SUCCESS], [LINK_ON_FAILURE]);
account.createOAuth2Session(OAuthProvider.GitHub, '[LINK_ON_SUCCESS]', '[LINK_ON_FAILURE]');
```
Users will be redirected to the OAuth2 provider's login page to log in. Once complete, your user will be redirected back to your app.
In your web application, you need to finish OAuth authentication using [Create session](/docs/references/cloud/client-web/account#createSession) endpoint. Both user ID and token secret will be provided to you in the URL params.
```js
const urlParams = new URLSearchParams(window.location.search);
const secret = urlParams.get('secret');
const userId = urlParams.get('userId');
await account.createSession(userId, secret);
```
{% /tabsitem %}
{% tabsitem #flutter title="Flutter" %}
```dart
// Flutter SDK
import 'package:appwrite/appwrite.dart';
final client = Client()
@@ -53,8 +64,12 @@ final client = Client()
final account = Account(client);
// Go to OAuth provider login page
await account.createOAuth2Session(provider: 'amazon');
await account.createOAuth2Session(provider: OAuthProvider.github);
```
User will be redirected to the OAuth2 provider's login page to log in. Once complete, your user will be redirected back to your app.
You can optionally configure `success` or `failure` redirect links for having custom logic for handling those scenarios.
{% /tabsitem %}
{% tabsitem #android title="Android" %}
@@ -82,8 +97,13 @@ val client = Client()
val account = Account(client)
// Go to OAuth provider login page
account.createOAuth2Session(provider = "amazon")
account.createOAuth2Session(provider = "github")
```
User will be redirected to the OAuth2 provider's login page to log in. Once complete, your user will be redirected back to your app.
You can optionally configure `success` or `failure` redirect links for having custom logic for handling those scenarios.
{% /tabsitem %}
{% tabsitem #apple title="Apple" %}
@@ -128,13 +148,14 @@ let account = Account(client)
// Go to OAuth provider login page
try await account.createOAuth2Session(provider: "amazon")
```
User will be redirected to the OAuth2 provider's login page to log in. Once complete, your user will be redirected back to your app.
You can optionally configure `success` or `failure` redirect links for having custom logic for handling those scenarios.
{% /tabsitem %}
{% /tabs %}
You'll be redirected to the OAuth 2 provider's login page to log in. Once complete, your user will be redirected back to your app.
You can optionally configure `success` or `failure` redirect links on web to handle success and failure scenarios.
# OAuth2 profile {% #profile %}
After authenticating a user through their OAuth2 provider, you can fetch their profile information such as their avatar image or name. To do this you can use the access token from the OAuth2 provider and make API calls to the provider.
@@ -143,7 +164,6 @@ After creating an OAuth 2 session, you can fetch the session to get information
{% multicode %}
```js
// Web SDK
import { Client, Account } from "appwrite";
const client = new Client();
@@ -159,7 +179,6 @@ console.log(session.providerAccessToken);
```
```dart
// Flutter SDK
import 'package:appwrite/appwrite.dart';
final client = Client()
@@ -179,7 +198,6 @@ print(session.providerAccessToken);
```
```kotlin
// Android SDK
import io.appwrite.Client
import io.appwrite.services.Account
@@ -200,7 +218,6 @@ print(session.providerAccessToken);
```
```swift
// Apple SDK
import Appwrite
let client = Client()
@@ -232,13 +249,12 @@ An OAuth 2 [session](/docs/references/cloud/models/session) will have the follow
You can use the `providerAccessToken` to make requests to your OAuth2 provider. Refer to the docs for the OAuth2 provider you're using to learn about making API calls with the access token.
# OAuth 2 profile {% #profile %}
# Refreshing OAuth2 tokens {% #refreshing-tokens %}
OAuth 2 sessions expire to protect from security risks. OAuth 2 sessions should be refreshed periodically, so access tokens don't expire. Check value of `providerAccessTokenExpiry` to know if the token is expired or is about to expire. Refreshing before every request might cause rate limit problems. You can do this by calling the [Update OAuth Session](/docs/references/cloud/client-web/account#updateSession) endpoint when ever your user visits your app.
OAuth2 sessions expire to protect from security risks. OAuth2 sessions should be refreshed periodically, so access tokens don't expire. Check value of `providerAccessTokenExpiry` to know if the token is expired or is about to expire. Refreshing before every request might cause rate limit problems. You can do this by calling the [Update session](/docs/references/cloud/client-web/account#updateSession) endpoint right before token expiry, or before first request after expiry.
{% multicode %}
```js
// Web
const promise = account.updateSession('[SESSION_ID]');
promise.then(function (response) {
@@ -248,7 +264,6 @@ promise.then(function (response) {
});
```
```dart
// Flutter
import 'package:appwrite/appwrite.dart';
final client = Client()
@@ -262,7 +277,6 @@ final result = await account.updateSession(
);
```
```kotlin
// Android
import io.appwrite.Client
import io.appwrite.services.Account
@@ -277,7 +291,6 @@ val response = account.updateSession(
);
```
```swift
// Apple
import Appwrite
let client = Client()

View File

@@ -8,7 +8,7 @@ Phone authentication lets users create accounts using their phone numbers and lo
# Send SMS message {% #init %}
Phone authentication is done using a two-step authentication process. When using phone authentication, the authentication request is initiated from the client application and an SMS message is sent to the user's phone. The SMS message will contain a secret the user can use to log in.
Phone authentication is done using a two-step authentication process. When using phone authentication, the authentication request is initiated from the client application and an SMS message is sent to the user's phone. The SMS message will contain a 6-digit number the user can use to log in.
Send an SMS message to initiate the authentication process. A **new account** will be created for this phone number if it has never been used before.
@@ -23,7 +23,7 @@ const client = new Client()
const account = new Account(client);
const sessionToken = await account.createPhoneSession(
const sessionToken = await account.createPhoneToken(
ID.unique(),
'+14255550123'
);
@@ -40,7 +40,7 @@ final client = Client()
final account = Account(client);
final sessionToken = await account.createPhoneSession(
final sessionToken = await account.createPhoneToken(
userId: ID.unique(),
phone: '+14255550123'
);
@@ -59,7 +59,7 @@ val client = Client()
val account = Account(client);
val sessionToken = account.createPhoneSession(
val sessionToken = account.createPhoneToken(
userId = ID.unique(),
phone = "+14255550123"
);
@@ -76,7 +76,7 @@ let client = Client()
let account = Account(client);
let sessionToken = try await account.createPhoneSession(
let sessionToken = try await account.createPhoneToken(
userId: ID.unique(),
phone: "+14255550123"
);
@@ -86,7 +86,7 @@ let userId = sessionToken.userId;
```graphql
mutation {
accountCreatePhoneSession(userId: "unique()", phone: "+14255550123") {
accountCreatePhoneToken(userId: "unique()", phone: "+14255550123") {
_id
userId
secret
@@ -99,7 +99,7 @@ mutation {
# Login {% #login %}
After initiating the phone authentication process, the returned user ID and secret are used to confirm the user. The secret will usually be a 6-digit number in the SMS message sent to the user.
After initiating the phone authentication process, the returned user ID and secret are used to authenticate the user. The secret will be a 6-digit number in the SMS message sent to the user.
{% multicode %}
@@ -112,7 +112,7 @@ const client = new Client()
const account = new Account(client);
const session = await account.updatePhoneSession(
const session = await account.createSession(
userId,
'[SECRET]'
);
@@ -127,7 +127,7 @@ final client = Client()
final account = Account(client);
final session = await account.updatePhoneSession(
final session = await account.createSession(
userId: userId,
secret: '[SECRET]'
);
@@ -144,7 +144,7 @@ val client = Client()
val account = Account(client);
val session = account.updatePhoneSession(
val session = account.createSession(
userId = userId,
secret = "[SECRET]"
);
@@ -159,7 +159,7 @@ let client = Client()
let account = Account(client);
let session = try await account.updatePhoneSession(
let session = try await account.createSession(
userId: userId,
secret: "[SECRET]"
);
@@ -167,7 +167,7 @@ let session = try await account.updatePhoneSession(
```graphql
mutation {
accountUpdatePhoneSession(userId: "[USER_ID]", secret: "[SECRET]") {
accountcreateSession(userId: "<USER_ID>", secret: "[SECRET]") {
_id
userId
provider

View File

@@ -20,7 +20,7 @@ const client = new Client()
const account = new Account(client);
const promise = account.create('[USER_ID]', 'email@example.com', '');
const promise = account.create(ID.unique(), 'email@example.com', 'password');
promise.then(function (response) {
console.log(response); // Success
@@ -89,7 +89,7 @@ mutation {
# Login {% #login %}
After you've created your account, users can be logged in using the [Create Email Session](/docs/references/cloud/client-web/account#createEmailSession) route.
After you've created your account, users can be logged in using the [Create Email Password Session](/docs/references/cloud/server-nodejs/account#createEmailPasswordSession) endpoint.
{% multicode %}
```js
@@ -101,7 +101,7 @@ const client = new Client()
const account = new Account(client);
const promise = account.createEmailSession('email@example.com', 'password');
const promise = account.createEmailPasswordSession('email@example.com', 'password');
promise.then(function (response) {
console.log(response); // Success
@@ -119,7 +119,7 @@ final client = Client()
final account = Account(client);
final session = await account.createEmailSession(
final session = await account.createEmailPasswordSession(
email: 'email@example.com',
password: 'password'
);
@@ -135,7 +135,7 @@ val client = Client()
val account = Account(client)
val session = account.createEmailSession(
val session = account.createEmailPasswordSession(
email = "email@example.com",
password = "password"
)
@@ -150,7 +150,7 @@ let client = Client()
let account = Account(client)
let session = try await account.createEmailSession(
let session = try await account.createEmailPasswordSession(
email: "email@example.com",
password: "password"
)
@@ -158,7 +158,7 @@ let session = try await account.createEmailSession(
```graphql
mutation {
accountCreateEmailSession(email: "email@example.com", password: "password") {
accountCreateEmailPasswordSession(email: "email@example.com", password: "password") {
_id
userId
provider
@@ -169,11 +169,12 @@ mutation {
{% /multicode %}
# More ways to authenticate {% #more-ways-to-authenticate %}
You can signup and login a user with an account create through
[email password](/docs/products/auth/email-password),
[phone (SMS)](/docs/products/auth/phone-sms),
[Anonymous](/docs/products/auth/anonymous)
[magic URL](/docs/products/auth/magic-url), and
[OAuth 2](/docs/products/auth/oauth2)
authentication.
You can signup and login a user with an account created through
[Email and password](/docs/products/auth/email-password),
[OAuth2](/docs/products/auth/oauth2),
[Magic URL](/docs/products/auth/magic-url),
[Email OTP](/docs/products/auth/email-otp),
[Phone (SMS)](/docs/products/auth/phone-sms),
and [Anonymous](/docs/products/auth/anonymous) authentications.
You can also use [Custom token](/docs/products/auth/custom-token) to implement your own authentication flow, or integrate with any external provider.

View File

@@ -16,15 +16,27 @@ Only keep user sessions active as long as needed and maintain exactly **one** in
| {% width=70 %} | Framework {% width=120 %} | Storage method |
|:----------------------------------------------------------------------------------------------------:|:---:|:----------------------------------------------------------------------------------------------------------------------:|
| {% only_dark %}{% icon_image src="/images/platforms/dark/javascript.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/javascript.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Web | Uses a secure session cookie and falls back to local storage when a session cookie is not available. |
| {% only_dark %}{% icon_image src="/images/platforms/dark/flutter.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/flutter.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Flutter | Uses a session cookie stored in Application Documents through the **path_provider** package. |
| {% only_dark %}{% icon_image src="/images/platforms/dark/apple.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/apple.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Apple | Uses a session cookie stored in **UserDefaults**. |
| {% only_dark %}{% icon_image src="/images/platforms/dark/android.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/android.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Android | Uses a session cookie stored in **SharedPreferences**. |
| {% only_dark %}{% icon_image src="/images/platforms/dark/javascript.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/javascript.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Web | Uses a secure cookie and falls back to local storage when a session cookie is not available. |
| {% only_dark %}{% icon_image src="/images/platforms/dark/flutter.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/flutter.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Flutter | Uses a cookie stored in Application Documents through the **path_provider** package. |
| {% only_dark %}{% icon_image src="/images/platforms/dark/apple.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/apple.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Apple | Uses a cookie stored in **UserDefaults**. |
| {% only_dark %}{% icon_image src="/images/platforms/dark/android.svg" alt="Javascript logo" size="m" /%}{% /only_dark %}{% only_light %}{% icon_image src="/images/platforms/android.svg" alt="Javascript logo" size="m" /%}{% /only_light %} | Android | Uses a cookie stored in **SharedPreferences**. |
# Users limit {% #users-limit %}
You can limit amount of users to be allowed to sign up in your application. Once the limit is reached, all new sign-ups will be blocked. This is useful for beta testing or only allowing moderated sign-ups into your application.
To set users limit, head to the Appwrite Console > **Authentication** > **Security**. By default it's unlimited and maximum configurable limit is 10,000.
# Session limits {% #session-limits %}
In Appwrite versions 1.2 and above, you can limit the number of active sessions created per user to prevent the accumulation of unused but active sessions. New sessions created by the same user past the session limit delete the oldest session.
You can limit the number of active sessions created per user to prevent the accumulation of unused but active sessions. The oldest session is deleted when creating sessions beyond the session limit.
You can change the session limit in the **Security** tab of the Auth Service in your Appwrite Console. The default session limit is 10 with a maximum configurable limit of 100.
You can change the session limit by heading to the Appwrite Console > **Authentication** > **Security**. The default session limit is 10 with a maximum configurable limit of 100.
# Session length {% #session-length %}
Every session must expire for security reasons. By default, sessions made in Appwrite will expire after 1 year. You can configure the expiration by heading to the Appwrite Console > **Authentication** > **Security**. You can not make it any longer than 1 year, and you can make it as short as you want.
When using short session lengths such as 5 minutes, we recommend sending request to [Update session](/docs/references/cloud/client-web/account#updateSession) endpoint everytime user performs an action. By doing that, user's session expiry is extended to session length. This means the session is invalidated within few minutes after user stops interacting with the application, and the user is logged out.
# Permissions {% #permissions %}

View File

@@ -0,0 +1,456 @@
---
layout: article
title: SSR login
description: How to implement SSR authentication with Appwrite
---
Server-side rendering (SSR) is fully supported with Appwrite. You can use Appwrite with many SSR-oriented frameworks, such as Next.js, SvelteKit, Nuxt, Gatsby, Remix, and more.
SSR is a technique where the server renders a web page and sending the fully rendered page to the client's web browser. This is in contrast to client-side rendering (CSR), where the client's web browser renders the page using JavaScript.
This guide will walk you through the process of implementing an SSR application with Appwrite.
# SSR authentication flow {% #ssr-auth-flow %}
In client-side rendered web apps, a [Client SDK](/docs/sdks#client) is used to perform authentication directly from the client's web browser.
With server-side rendered web apps, a [Server SDK](/docs/sdks#server) is used to handle authentication against Appwrite. Authentication data is passed from the client's web browser to your server, and then your server makes requests to Appwrite on behalf of the client.
Here's a high-level overview of the authentication flow:
1. The user enters their credentials in their web browser.
2. The browser sends the credentials to your server.
3. Your server uses the Server SDK to authenticate the user with Appwrite.
4. If the authentication is successful, your server sends a session cookie to the client's web browser.
5. The client's web browser sends the session cookie to your server with subsequent request.
6. Your server uses the session cookie to make authenticated requests to Appwrite on behalf of the client.
{% only_dark %}
![CSR vs SSR flow diagram](/images/docs/auth/ssr/dark/ssr.png)
{% /only_dark %}
{% only_light %}
![CSR vs SSR flow diagram](/images/docs/auth/ssr/ssr.png)
{% /only_light %}
# Initialize clients {% #initialize-clients %}
{% info title="Server SDK required" %}
Server-side rendering requires a [Server SDK](/docs/sdks#server) instead of a Client SDK.
{% /info %}
In SSR, your server-side application will be making authentication requests to Appwrite and passing session cookies to your client-side app on the browser.
We'll need to initialize two Appwrite clients, one for admin requests and one for session-based requests.
## Admin client {% #admin-client %}
{% info title="Admin clients" %}
Admin clients should only be used if you need to perform admin actions that bypass permissions
or [unauthenticated requests that bypass rate limits](#rate-limits).
{% /info %}
To initialize the admin client, we'll need to first [generated an API key](/docs/advanced/platform/api-keys#create-api-key).
The API key should have the following scope in order to perform authentication:
| Category {% width=120 %} | Required scopes | Purpose |
|-----------|---------------------|---------|
| Sessions | `sessions.write` | Allows API key to create, update, and delete sessions. |
{% multicode %}
```js
import { Client } from "node-appwrite"; // Using the server SDK
const adminClient = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
```
```php
use Appwrite\Client;
use Appwrite\Services\Account;
$adminClient = (new Client())
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setKey('<YOUR_API_KEY>'); // Your secret API key
```
{% /multicode %}
It is important to use an API key, as this will allow your server requests to bypass [rate limits](/docs/advanced/platform/rate-limits). If you don't use an API key, your server will be rate limited as if it were a client from a single IP address.
## Session client {% #session-client %}
The session client will be used to make requests to Appwrite on behalf of the end-user.
It will be initialized with the session, usually stored within a cookie.
You should create a new client for each request and **never** share the client between requests.
{% multicode %}
```js
const sessionClient = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const session = req.cookies.session; // Get the session cookie from the request
if (session) {
sessionClient.setSession(session);
}
```
```php
$sessionClient = (new Client())
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>'); // Your project ID
$session = $_COOKIE['session']; // Get the session cookie from the request
if ($session) {
$sessionClient->setSession($session);
}
```
{% /multicode %}
# Creating email/password sessions {% #creating-sessions %}
The most straightforward type of session to integrate is email/password.
Create an endpoint using your server's framework of choice that accepts a username and password, and then makes a request to Appwrite to create a session.
Once you have a session object, you can store it in a cookie. This will allow your users make authenticated requests to the Appwrite API from your server.
Use the `secret` property of the session object as the cookie value. The `expire` property of the session object should be used as the cookie's max age.
Here's an example with Express and PHP, but the same concepts apply to all most frameworks.
{% multicode %}
```js
import express from 'express';
// Initialize admin client here
// ...
app.post('/login', async (req, res) => {
// Get email and password from request
const { email, password } = req.body;
const account = new Account(adminClient);
try {
// Create the session using the Appwrite client
const session = await account.createEmailPasswordSession(email, password);
// Set the session cookie
res.cookie('session', session.secret, { // use the session secret as the cookie value
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: sesion.expire
path: '/',
});
res.status(200).json({ success: true });
} catch (e) {
res.status(400).json({ success: false, error: e.message });
}
});
```
```php
<?php
// Initialize admin client here
// ...
// Get email and password from request
$email = $_POST['email'];
$password = $_POST['password'];
try {
$account = new Account($adminClient);
// Create the session using the Appwrite client
$session = $account->createEmailPasswordSession($email, $password);
// Set the session cookie
setcookie('session', $session['secret'], [
'httpOnly' => true,
'secure' => true,
'sameSite' => 'strict',
'maxAge' => $session['expire'],
'path' => '/',
]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
```
{% /multicode %}
We also recommend using the `httpOnly`, `secure`, and `sameSite` cookie options to ensure that the cookie is only sent over HTTPS,
and is not accessible to JavaScript. This will prevent XSS attacks.
# Making authenticated requests {% #making-authenticated-requests %}
Once a user has a session cookie, which will be set by the browser when it receives the `/login` endpoint's response, they can use it to make authenticated requests to your server.
To enable this, you will need to read the cookie value from the request, and then pass it to the Appwrite client, using the `setSession` helper.
When the browser makes a request to your domain's endpoints, it will automatically include session cookies.
{% multicode %}
```js
// Initialize the session client here
app.get('/user', async (req, res) => {
// First, read the session cookie from the request
const session = req.cookies.session;
// If the session cookie is not present, return an error
if (!session) {
return res.status(401).json({ success: false, error: 'Unauthorized' });
}
// Pass the session cookie to the Appwrite client
sessionClient.setSession(session);
// Now, you can make authenticated requests to the Appwrite API
const account = new Account(sessionClient);
try {
const user = await account.get();
res.status(200).json({ success: true, user });
} catch (e) {
res.status(400).json({ success: false, error: e.message });
}
});
```
```php
<?php
// Initialize the session client here
// First, read the session cookie from the request
$session = $_COOKIE['session'];
// If the session cookie is not present, return an error
if (!$session) {
return http_response_code(401);
}
// Pass the session cookie to the Appwrite client
$sessionClient->setSession($session);
$account = new Account($sessionClient);
// Now, you can make authenticated requests to the Appwrite API
try {
$user = $account->get();
echo json_encode(['success' => true, 'user' => $user]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
```
{% /multicode %}
# Rate limits {% #rate-limits %}
Unauthenticated requests are subject to [rate limits](/docs/advanced/platform/rate-limits).
Normally, rate limits are applied by an abuse key, which is usually a combination of IP and another factor like user ID.
When you make unauthenticated requests from your server, however, all requests originate from the same IP and no user ID is provided.
This means that all unauthenticated requests from your server will be **subject to the same rate limits**.
These rate limits protect your Appwrite server from abuse, if you need to make unauthenticated requests from your server,
there are ways to bypass rate limits.
# Making unauthenticated requests {% #making-unauthenticated-requests %}
Unauthenticated requests are used for displaying information to users before they log in.
For example some apps may display all public posts on the home page, and only show private posts to logged-in users.
There are two ways to make unauthenticated requests:
{% table %}
* Guest sessions
* Admin clients
---
* Uses the `createAnonymousSession` method to create a guest session.
* Uses an API key to bypass rate limits.
---
* Creates a session for unauthenticated users so each user has their own rate limit.
* Bypasses rate limits completely because API keys are not limited.
---
* Still respects access permissions.
* Also bypasses access permissions.
---
* Can be turned into a full session later by creating an account.
* Cannot be later turned into a full session.
{% /table %}
You can create a guest session using the `createAnonymousSession` method.
This will create a session for unauthenticated users, and each user will have their own rate limit.
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const account = new sdk.Account(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
;
const promise = account.createAnonymousSession();
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Account;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
;
$account = new Account($client);
$result = $account->createAnonymousSession();
```
{% /multicode %}
# Forwarding user agent {% #forwarding-user-agent %}
Appwrite sessions record some information about the client. To set this information in a server-side context use the `setForwardedUserAgent` to set the end-user's user agent. While optional, these can be useful for debugging and security purposes.
{% multicode %}
```js
client.setForwardedUserAgent(req.headers['user-agent']);
```
```php
<?php
$client->setForwardedUserAgent($_SERVER['HTTP_USER_AGENT']);
```
{% /multicode %}
# OAuth2 {% #oauth2 %}
Server-side OAuth2 authentication requires two server endpoints:
Create an initial endpoint that redirects the user to the OAuth2 provider's authentication page using Appwrite's `createOAuth2Token` method. After authenticating with the provider, the user will be redirected to the `success` URL with `userId` and `secret` URL parameters.
{% multicode %}
```js
import { Client, Account, OAuthProvider } from "node-appwrite"; // Using the server SDK
const adminClient = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<API_KEY>'); // Your secret API key
app.get('/oauth', async (req, res) => {
const account = new Account(adminClient);
const redirectUrl = await account.createOAuth2Token(
OAuthProvider.GitHub, // Provider
'https://example.com/oauth/success', // Success URL
'https://example.com/oauth/failure', // Failure URL
);
res.redirect(redirectUrl);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Account;
use Appwrite\Enums\OAuthProvider;
$adminClient = (new Client())
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setKey('<API_KEY>'); // Your secret API key
$account = new Account($adminClient);
$redirectUrl = $account->createOAuth2Token(
OAuthProvider::GITHUB(),
'https://example.com/oauth/success', // Success URL
'https://example.com/oauth/failure', // Failure URL
);
header('Location' . $redirectUrl);
```
{% /multicode %}
Next, create a success callback endpoint that receives the `userId` and `secret` URL parameters, and then calls `createSession` on the server side. This endpoint returns a session object, which you can store in a cookie.
{% multicode %}
```js
app.get('/oauth/success', async (req, res) => {
const account = new Account(adminClient);
// Get the userId and secret from the URL parameters
const { userId, secret } = req.query;
try {
// Create the session using the Appwrite client
const session = await account.createSession(userId, secret);
// Set the session cookie
res.cookie('session', session.secret, { // Use the session secret as the cookie value
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: sesion.expire
path: '/',
});
res.status(200).json({ success: true });
} catch (e) {
res.status(400).json({ success: false, error: e.message });
}
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Account;
$adminClient = (new Client())
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setKey('<API_KEY>'); // Your secret API key
$account = new Account($adminClient);
// Get the userId and secret from the URL parameters
$userId = $_GET['userId'];
$secret = $_GET['secret'];
try {
// Create the session using the Appwrite client
$session = $account->createSession($userId, $secret);
// Set the session cookie
setcookie('session', $session['secret'], [
'httpOnly' => true,
'secure' => true,
'sameSite' => 'strict',
'maxAge' => $session['expire'],
'path' => '/',
]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
```
{% /multicode %}
Now the cookie is set, it will be passed to the server with subsequent requests, and you can use it to make authenticated requests to the Appwrite API on behalf of the end-user.

View File

@@ -8,7 +8,7 @@ Teams are a good way to allow users to share access to resources.
For example, in a todo app, a user can [create a team](/docs/references/cloud/client-web/teams#create) for one of their todo lists and [invite another user](/docs/references/cloud/client-web/teams#createMembership) to the team to grant the other user access.
You can further give special rights to parts of a team using team roles.
The invited user can [accept the invitation](/docs/references/cloud/client-web/teams#updateMembershipStatus) to gain access. If the user's ever removed from the team, they'll lose access again.
The invited user can [accept the invitation](/docs/references/cloud/client-web/teams#updateMembershipStatus) to gain access. If the user is ever removed from the team, they'll lose access again.
# Create team {% #create %}
For example, we can create a team called `teachers` with roles `maths`, `sciences`, `arts`, and `literature`.
@@ -25,7 +25,7 @@ const teams = new Teams(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setProject('<PROJECT_ID>') // Your project ID
;
const promise = teams.create(
@@ -49,7 +49,7 @@ void main() { // Init SDK
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setProject('<PROJECT_ID>') // Your project ID
;
Future result = teams.create(
teamId: 'teachers',
@@ -70,7 +70,7 @@ import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setProject("<PROJECT_ID>") // Your project ID
let teams = Teams(client)
@@ -86,7 +86,7 @@ import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setProject("<PROJECT_ID>") // Your project ID
val teams = Teams(client)
@@ -113,7 +113,7 @@ const teams = new Teams(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setProject('<PROJECT_ID>') // Your project ID
;
const promise = teams.createMembership(
@@ -137,7 +137,7 @@ void main() { // Init SDK
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setProject('<PROJECT_ID>') // Your project ID
;
Future result = teams.createMembership(
teamId: 'teachers',
@@ -158,7 +158,7 @@ import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setProject("<PROJECT_ID>") // Your project ID
let teams = Teams(client)
@@ -174,7 +174,7 @@ import io.appwrite.services.Teams
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setProject("<PROJECT_ID>") // Your project ID
val teams = Teams(client)

View File

@@ -0,0 +1,37 @@
---
layout: article
title: Tokens
description: What are tokens and how to use them in Appwrite
---
Tokens are short-lived secrets created by an that can be exchanged for session by a [Client SDK](/docs/sdks#client) to log in users.
Tokens are created with the following properties:
| Property | Type | Description |
| ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `$id` | string | Token ID. |
| `$createdAt` | string | Token creation date in ISO 8601 format. |
| `userId` | string | User ID. |
| `secret` | string | Token secret key. This will return an empty string unless the response is returned using an API key or as part of a webhook payload. |
| `expire` | string | Token expiration date in ISO 8601 format. |
Many Appwrite authentication methods use a token-base flow to authenticate users. For token-based authentication methods, there are two high level steps to authenticate a user:
# Create a token {% #create-a-token %}
First, create a token for the user.
Methods that create tokens include [Magic URL login](/docs/products/auth/magic-url), [Email OTP login](/docs/products/auth/email-otp), [Phone (SMS) login](/docs/products/auth/phone-sms), and [Custom token](/docs/products/auth/custom-token/#create-custom-token).
These methods transfer the token `userId` and `secret` to the client, via a URL, email, SMS, or other method. The client then uses the token to create a session.
Custom tokens can be created using the [Create token](/docs/references/cloud/server-nodejs/users#createToken) endpoint of the [Users API](/docs/products/auth/users).
# Create a session using the token {% #create-session-using-token %}
After the token is created, the client uses the token to create a session. The session is then used to authenticate the user for subsequent requests.
To create a session, the client sends the token to the server using the [Create session](/docs/references/cloud/server-nodejs/account#createSession) endpoint of the [Account API](/docs/products/auth/users). The server then returns a session object.
When the session is successfully created, the session is stored in a persistent manner and you can now do requests as authorized user from the application.

View File

@@ -10,7 +10,7 @@ If you need to act on behalf of users through an Appwrite Function or your own b
{% partial file="account-vs-user.md" /%}
The users API can be used to create users, import users, update user info, get user audit logs, and remove users.
The [Users API](/docs/references/cloud/client-web/users) can be used to create users, import and export users, update user info, get user audit logs, and remove users.
{% arrow_link href="/docs/references/cloud/server-nodejs/users" %}
Learn more in the Users API references

View File

@@ -35,7 +35,7 @@ client
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = databases.createCollection('[DATABASE_ID]', '[COLLECTION_ID]', '[NAME]');
const promise = databases.createCollection('<DATABASE_ID>', '[COLLECTION_ID]', '[NAME]');
promise.then(function (response) {
console.log(response);
@@ -58,7 +58,7 @@ client
;
let promise = databases.createCollection('[DATABASE_ID]', '[COLLECTION_ID]', '[NAME]');
let promise = databases.createCollection('<DATABASE_ID>', '[COLLECTION_ID]', '[NAME]');
promise.then(function (response) {
console.log(response);
@@ -82,7 +82,7 @@ $client
$databases = new Databases($client);
$result = $databases->createCollection('[DATABASE_ID]', '[COLLECTION_ID]', '[NAME]');
$result = $databases->createCollection('<DATABASE_ID>', '[COLLECTION_ID]', '[NAME]');
```
```python
from appwrite.client import Client
@@ -98,7 +98,7 @@ client = Client()
databases = Databases(client)
result = databases.create_collection('[DATABASE_ID]', '[COLLECTION_ID]', '[NAME]')
result = databases.create_collection('<DATABASE_ID>', '[COLLECTION_ID]', '[NAME]')
```
```ruby
require 'Appwrite'
@@ -112,7 +112,7 @@ client = Client.new
databases = Databases.new(client)
response = databases.create_collection(database_id: '[DATABASE_ID]', collection_id: '[COLLECTION_ID]', name: '[NAME]')
response = databases.create_collection(database_id: '<DATABASE_ID>', collection_id: '[COLLECTION_ID]', name: '[NAME]')
puts response.inspect
```
@@ -129,8 +129,8 @@ var client = new Client()
var databases = new Databases(client);
Collection result = await databases.CreateCollection(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
name: "[NAME]");
```
```dart
@@ -147,7 +147,7 @@ void main() { // Init SDK
;
Future result = databases.createCollection(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
name: '[NAME]',
);
@@ -172,8 +172,8 @@ val client = Client(context)
val databases = Databases(client)
val response = databases.createCollection(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
name = "[NAME]",
)
```
@@ -190,8 +190,8 @@ Client client = new Client()
Databases databases = new Databases(client);
databases.createCollection(
"[DATABASE_ID]",
"[COLLECTION_ID]",
"<DATABASE_ID>",
"<COLLECTION_ID>",
"[NAME]",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
@@ -214,8 +214,8 @@ let client = Client()
let databases = Databases(client)
let collection = try await databases.createCollection(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
name: "[NAME]"
)
```

View File

@@ -31,7 +31,7 @@ client
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = databases.create('[DATABASE_ID]', '[NAME]');
const promise = databases.create('<DATABASE_ID>', '[NAME]');
promise.then(function (response) {
console.log(response);
@@ -54,7 +54,7 @@ client
;
let promise = databases.create('[DATABASE_ID]', '[NAME]');
let promise = databases.create('<DATABASE_ID>', '[NAME]');
promise.then(function (response) {
console.log(response);
@@ -78,7 +78,7 @@ $client
$databases = new Databases($client);
$result = $databases->create('[DATABASE_ID]', '[NAME]');
$result = $databases->create('<DATABASE_ID>', '[NAME]');
```
```python
from appwrite.client import Client
@@ -94,7 +94,7 @@ client = Client()
databases = Databases(client)
result = databases.create('[DATABASE_ID]', '[NAME]')
result = databases.create('<DATABASE_ID>', '[NAME]')
```
```ruby
require 'Appwrite'
@@ -108,7 +108,7 @@ client = Client.new
databases = Databases.new(client)
response = databases.create(database_id: '[DATABASE_ID]', name: '[NAME]')
response = databases.create(database_id: '<DATABASE_ID>', name: '[NAME]')
puts response.inspect
```
@@ -125,7 +125,7 @@ var client = new Client()
var databases = new Databases(client);
Database result = await databases.Create(
databaseId: "[DATABASE_ID]",
databaseId: "<DATABASE_ID>",
name: "[NAME]");
```
```dart
@@ -142,7 +142,7 @@ void main() { // Init SDK
;
Future result = databases.create(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
name: '[NAME]',
);
@@ -166,7 +166,7 @@ val client = Client(context)
val databases = Databases(client)
val response = databases.create(
databaseId = "[DATABASE_ID]",
databaseId = "<DATABASE_ID>",
name = "[NAME]",
)
```
@@ -183,7 +183,7 @@ Client client = new Client()
Databases databases = new Databases(client);
databases.create(
"[DATABASE_ID]",
"<DATABASE_ID>",
"[NAME]",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
@@ -206,7 +206,7 @@ let client = Client()
let databases = Databases(client)
let database = try await databases.create(
databaseId: "[DATABASE_ID]",
databaseId: "<DATABASE_ID>",
name: "[NAME]"
)
```

View File

@@ -25,7 +25,7 @@ const client = new Client()
const databases = new Databases(client);
const promise = databases.createDocument(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
ID.unique(),
{}
@@ -49,7 +49,7 @@ void main() async {
try {
final document = databases.createDocument(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
documentId: ID.unique(),
data: {}
@@ -72,8 +72,8 @@ suspend fun main() {
try {
val document = databases.createDocument(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documentId = ID.unique(),
data = mapOf("a" to "b"),
)
@@ -95,8 +95,8 @@ func main() async throws {
do {
let document = try await databases.createDocument(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: ID.unique(),
data: [:]
)
@@ -108,8 +108,8 @@ func main() async throws {
```graphql
mutation {
databasesCreateDocument(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: "[DOCUMENT_ID]",
data: "{}"
) {
@@ -154,8 +154,8 @@ const client = new Client()
const databases = new Databases(client);
let promise = databases.listDocuments(
"[DATABASE_ID]",
"[COLLECTION_ID]",
"<DATABASE_ID>",
"<COLLECTION_ID>",
[
Query.equal('title', 'Avatar')
]
@@ -179,7 +179,7 @@ void main() async {
try {
final documents = await databases.listDocuments(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
queries: [
Query.equal('title', 'Avatar')
@@ -204,8 +204,8 @@ suspend fun main() {
try {
val documents = databases.listDocuments(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = listOf(
Query.equal("title", "Avatar")
)
@@ -228,8 +228,8 @@ func main() async throws {
do {
let documents = try await databases.listDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: [
Query.equal("title", "Avatar")
]
@@ -242,8 +242,8 @@ func main() async throws {
```graphql
query {
databasesListDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: ["equal(\"title\", [\"Avatar\"])"]
) {
total

View File

@@ -23,7 +23,7 @@ const client = new Client()
const databases = new Databases(client);
databases.listDocuments(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
[
Query.orderAsc('title'),
@@ -43,7 +43,7 @@ void main() async {
try {
final documents = await databases.listDocuments(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
queries: [
Query.orderAsc('title')
@@ -69,8 +69,8 @@ suspend fun main() {
try {
val documents = databases.listDocuments(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = [
Query.orderAsc("title")
]
@@ -94,8 +94,8 @@ func main() async throws {
do {
let documents = try await databases.listDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: [
Query.orderAsc("title")
]
@@ -109,8 +109,8 @@ func main() async throws {
```graphql
query {
databasesListDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]"
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>"
queries: ["orderAsc(\"title\")"]
) {
total
@@ -137,7 +137,7 @@ In the example below, the movies returned will be first sorted by `title` in asc
// List documents and sort based on multiple attributes
databases.listDocuments(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
[
Query.orderAsc('title'), // Order first by title in ascending order
@@ -152,7 +152,7 @@ databases.listDocuments(
// List documents and sort based on multiple attributes
try {
final documents = await databases.listDocuments(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
queries: [
Query.orderAsc('title'), // Order by title in ascending order
@@ -170,8 +170,8 @@ try {
// List documents and sort based on multiple attributes
try {
val documents = databases.listDocuments(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = [
Query.orderAsc("title"), // Order by title in ascending order
Query.orderDesc("year") // Order by year in descending order
@@ -188,8 +188,8 @@ try {
// List documents and sort based on multiple attributes
do {
let documents = try await databases.listDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: [
Query.orderAsc("title"), // Order by title in ascending order
Query.orderDesc("year") // Order by year in descending order
@@ -202,8 +202,8 @@ do {
```graphql
query {
databasesListDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: ["orderAsc(\"title\")", "orderDesc(\"year\")"]
) {
total

View File

@@ -31,7 +31,7 @@ const databases = new Databases(client);
// Page 1
const page1 = await databases.listDocuments(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
[
Query.limit(25),
@@ -41,7 +41,7 @@ const page1 = await databases.listDocuments(
// Page 2
const page2 = await databases.listDocuments(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
[
Query.limit(25),
@@ -60,7 +60,7 @@ void main() async {
final databases = Databases(client);
final page1 = await databases.listDocuments(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
queries: [
Query.limit(25),
@@ -69,7 +69,7 @@ void main() async {
);
final page2 = await databases.listDocuments(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
queries: [
Query.limit(25),
@@ -91,8 +91,8 @@ suspend fun main() {
val databases = Databases(client)
val page1 = databases.listDocuments(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = [
Query.limit(25),
Query.offset(0)
@@ -100,8 +100,8 @@ suspend fun main() {
)
val page2 = databases.listDocuments(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = [
Query.limit(25),
Query.offset(25)
@@ -121,8 +121,8 @@ func main() async throws {
let databases = Databases(client)
let page1 = try await databases.listDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: [
Query.limit(25),
Query.offset(0)
@@ -130,8 +130,8 @@ func main() async throws {
)
let page2 = try await databases.listDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: [
Query.limit(25),
Query.offset(25)
@@ -167,7 +167,7 @@ const databases = new Databases(client);
// Page 1
const page1 = await databases.listDocuments(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
[
Query.limit(25),
@@ -178,7 +178,7 @@ const lastId = page1.documents[page1.documents.length - 1].$id;
// Page 2
const page2 = await databases.listDocuments(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
[
Query.limit(25),
@@ -198,7 +198,7 @@ void main() async {
final databases = Databases(client);
final page1 = await databases.listDocuments(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
queries: [
Query.limit(25)
@@ -208,7 +208,7 @@ void main() async {
final lastId = page1.documents[page1.documents.length - 1].$id;
final page2 = await databases.listDocuments(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
queries: [
Query.limit(25),
@@ -233,8 +233,8 @@ suspend fun main() {
val databases = Databases(client)
val page1 = databases.listDocuments(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = [
Query.limit(25)
]
@@ -243,8 +243,8 @@ suspend fun main() {
val lastId = page1.documents[page1.documents.size - 1].$id
val page2 = databases.listDocuments(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = [
Query.limit(25),
Query.cursorAfter(lastId)
@@ -264,8 +264,8 @@ func main() async throws {
let databases = Databases(client)
let page1 = try await databases.listDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: [
Query.limit(25)
]
@@ -274,8 +274,8 @@ func main() async throws {
let lastId = page1.documents[page1.documents.count - 1].$id
let page2 = try await databases.listDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: [
Query.limit(25),
Query.cursorAfter(lastId)

View File

@@ -10,9 +10,12 @@ Many list endpoints in Appwrite allow you to filter, sort, and paginate results
Appwrite SDKs provide a `Query` class to help you build queries. The `Query` class has a method for each type of supported query.
| Query | Description |
{% tabs %}
{% tabsitem #nodejs title="Node.js" %}
| Example | Description |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `Query.select(["name", "title"])` | Select which attributes should be returned from a document. |
| `Query.or([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches any of the nested sub-queries in the array passed in. |
| `Query.equal("title", ["Iron Man"])` | Returns document if attribute is equal to any value in the provided array. |
| `Query.notEqual("title", ["Iron Man"])` | Returns document if attribute is not equal to any value in the provided array. |
| `Query.lessThan("score", 10)` | Returns document if attribute is less than the provided value. |
@@ -24,6 +27,8 @@ Appwrite SDKs provide a `Query` class to help you build queries. The `Query` cla
| `Query.isNotNull("name")` | Returns documents where attribute value is **not** null. |
| `Query.startsWith("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query.endsWith("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query.contains("ingredients", ['apple', 'banana'])` | Returns documents if a the array attribute contains the specified elements. |
| `Query.contains("name", "Tom")` | Returns documents if a string attributes is like the pattern specified. |
| `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query.orderDesc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.orderAsc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
@@ -31,7 +36,252 @@ Appwrite SDKs provide a `Query` class to help you build queries. The `Query` cla
| `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorAfter("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
{% /tabsitem %}
{% tabsitem #php title="PHP" %}
| Example | Description |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `Query::select(["name", "title"])` | Select which attributes should be returned from a document. |
| `Query::or([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches any of the nested sub-queries in the array passed in. |
| `Query::equal("title", ["Iron Man"])` | Returns document if attribute is equal to any value in the provided array. |
| `Query::notEqual("title", ["Iron Man"])` | Returns document if attribute is not equal to any value in the provided array. |
| `Query::lessThan("score", 10)` | Returns document if attribute is less than the provided value. |
| `Query::lessThanEqual("score", 10)` | Returns document if attribute is less than or equal to the provided value. |
| `Query::greaterThan("score", 10)` | Returns document if attribute is greater than the provided value. |
| `Query::greaterThanEqual("score", 10)` | Returns document if attribute is greater than or equal to the provided value. |
| `Query::between("price", 5, 10)` | Returns document if attribute value falls between the two values. The boundary values are inclusive and can be strings or numbers. |
| `Query::isNull("name")` | Returns documents where attribute value is null. |
| `Query::isNotNull("name")` | Returns documents where attribute value is **not** null. |
| `Query::startsWith("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query::endsWith("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query::contains("ingredients", ['apple', 'banana'])` | Returns documents if a the array attribute contains the specified elements. |
| `Query::contains("name", "Tom")` | Returns documents if a string attributes is like the pattern specified. |
| `Query::search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query::orderDesc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query::orderAsc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query::limit(25)` | Limits the number of results returned by the query. Used for [pagination](/docs/products/databases/pagination). If the limit query is not used, the limit defaults to 25 results. |
| `Query::offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query::cursorAfter("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query::cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
{% /tabsitem %}
{% tabsitem #python title="Python" %}
| Example | Description |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `Query.select(["name", "title"])` | Select which attributes should be returned from a document. |
| `Query.or([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches any of the nested sub-queries in the array passed in. |
| `Query.and([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches all of the nested sub-queries in the array passed in. |
| `Query.equal("title", ["Iron Man"])` | Returns document if attribute is equal to any value in the provided array. |
| `Query.not_equal("title", ["Iron Man"])` | Returns document if attribute is not equal to any value in the provided array. |
| `Query.less_than("score", 10)` | Returns document if attribute is less than the provided value. |
| `Query.less_than_equal("score", 10)` | Returns document if attribute is less than or equal to the provided value. |
| `Query.greater_than("score", 10)` | Returns document if attribute is greater than the provided value. |
| `Query.greater_than_equal("score", 10)` | Returns document if attribute is greater than or equal to the provided value. |
| `Query.between("price", 5, 10)` | Returns document if attribute value falls between the two values. The boundary values are inclusive and can be strings or numbers. |
| `Query.is_null("name")` | Returns documents where attribute value is null. |
| `Query.is_not_null("name")` | Returns documents where attribute value is **not** null. |
| `Query.starts_with("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query.ends_with("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query.contains("ingredients", ['apple', 'banana'])` | Returns documents if a the array attribute contains the specified elements. |
| `Query.contains("name", "Tom")` | Returns documents if a string attributes is like the pattern specified. |
| `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query.order_desc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.order_asc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.limit(25)` | Limits the number of results returned by the query. Used for [pagination](/docs/products/databases/pagination). If the limit query is not used, the limit defaults to 25 results. |
| `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursor_after("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursor_before("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
{% /tabsitem %}
{% tabsitem #ruby title="Ruby" %}
| Example | Description |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `Query.select(["name", "title"])` | Select which attributes should be returned from a document. |
| `Query.or([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches any of the nested sub-queries in the array passed in. |
| `Query.equal("title", ["Iron Man"])` | Returns document if attribute is equal to any value in the provided array. |
| `Query.not_equal("title", ["Iron Man"])` | Returns document if attribute is not equal to any value in the provided array. |
| `Query.less_than("score", 10)` | Returns document if attribute is less than the provided value. |
| `Query.less_than_equal("score", 10)` | Returns document if attribute is less than or equal to the provided value. |
| `Query.greater_than("score", 10)` | Returns document if attribute is greater than the provided value. |
| `Query.greater_than_equal("score", 10)` | Returns document if attribute is greater than or equal to the provided value. |
| `Query.between("price", 5, 10)` | Returns document if attribute value falls between the two values. The boundary values are inclusive and can be strings or numbers. |
| `Query.is_null("name")` | Returns documents where attribute value is null. |
| `Query.is_not_null("name")` | Returns documents where attribute value is **not** null. |
| `Query.starts_with("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query.ends_with("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query.contains("ingredients", ['apple', 'banana'])` | Returns documents if a the array attribute contains the specified elements. |
| `Query.contains("name", "Tom")` | Returns documents if a string attributes is like the pattern specified. |
| `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query.order_desc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.order_asc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.limit(25)` | Limits the number of results returned by the query. Used for [pagination](/docs/products/databases/pagination). If the limit query is not used, the limit defaults to 25 results. |
| `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursor_after("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursor_before("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
{% /tabsitem %}
{% tabsitem #deno title="Deno" %}
| Example | Description |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `Query.select(["name", "title"])` | Select which attributes should be returned from a document. |
| `Query.or([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches any of the nested sub-queries in the array passed in. |
| `Query.equal("title", ["Iron Man"])` | Returns document if attribute is equal to any value in the provided array. |
| `Query.notEqual("title", ["Iron Man"])` | Returns document if attribute is not equal to any value in the provided array. |
| `Query.lessThan("score", 10)` | Returns document if attribute is less than the provided value. |
| `Query.lessThanEqual("score", 10)` | Returns document if attribute is less than or equal to the provided value. |
| `Query.greaterThan("score", 10)` | Returns document if attribute is greater than the provided value. |
| `Query.greaterThanEqual("score", 10)` | Returns document if attribute is greater than or equal to the provided value. |
| `Query.between("price", 5, 10)` | Returns document if attribute value falls between the two values. The boundary values are inclusive and can be strings or numbers. |
| `Query.isNull("name")` | Returns documents where attribute value is null. |
| `Query.isNotNull("name")` | Returns documents where attribute value is **not** null. |
| `Query.startsWith("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query.endsWith("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query.contains("ingredients", ['apple', 'banana'])` | Returns documents if a the array attribute contains the specified elements. |
| `Query.contains("name", "Tom")` | Returns documents if a string attributes is like the pattern specified. |
| `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query.orderDesc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.orderAsc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.limit(25)` | Limits the number of results returned by the query. Used for [pagination](/docs/products/databases/pagination). If the limit query is not used, the limit defaults to 25 results. |
| `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorAfter("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
{% /tabsitem %}
{% tabsitem #dart title="Dart" %}
| Example | Description |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `Query.select(["name", "title"])` | Select which attributes should be returned from a document. |
| `Query.or([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches any of the nested sub-queries in the array passed in. |
| `Query.equal("title", ["Iron Man"])` | Returns document if attribute is equal to any value in the provided array. |
| `Query.notEqual("title", ["Iron Man"])` | Returns document if attribute is not equal to any value in the provided array. |
| `Query.lessThan("score", 10)` | Returns document if attribute is less than the provided value. |
| `Query.lessThanEqual("score", 10)` | Returns document if attribute is less than or equal to the provided value. |
| `Query.greaterThan("score", 10)` | Returns document if attribute is greater than the provided value. |
| `Query.greaterThanEqual("score", 10)` | Returns document if attribute is greater than or equal to the provided value. |
| `Query.between("price", 5, 10)` | Returns document if attribute value falls between the two values. The boundary values are inclusive and can be strings or numbers. |
| `Query.isNull("name")` | Returns documents where attribute value is null. |
| `Query.isNotNull("name")` | Returns documents where attribute value is **not** null. |
| `Query.startsWith("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query.endsWith("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query.contains("ingredients", ['apple', 'banana'])` | Returns documents if a the array attribute contains the specified elements. |
| `Query.contains("name", "Tom")` | Returns documents if a string attributes is like the pattern specified. |
| `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query.orderDesc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.orderAsc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.limit(25)` | Limits the number of results returned by the query. Used for [pagination](/docs/products/databases/pagination). If the limit query is not used, the limit defaults to 25 results. |
| `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorAfter("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
{% /tabsitem %}
{% tabsitem #swift title="Swift" %}
| Example | Description |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `Query.select(["name", "title"])` | Select which attributes should be returned from a document. |
| `Query.or([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches any of the nested sub-queries in the array passed in. |
| `Query.equal("title", ["Iron Man"])` | Returns document if attribute is equal to any value in the provided array. |
| `Query.notEqual("title", ["Iron Man"])` | Returns document if attribute is not equal to any value in the provided array. |
| `Query.lessThan("score", 10)` | Returns document if attribute is less than the provided value. |
| `Query.lessThanEqual("score", 10)` | Returns document if attribute is less than or equal to the provided value. |
| `Query.greaterThan("score", 10)` | Returns document if attribute is greater than the provided value. |
| `Query.greaterThanEqual("score", 10)` | Returns document if attribute is greater than or equal to the provided value. |
| `Query.between("price", 5, 10)` | Returns document if attribute value falls between the two values. The boundary values are inclusive and can be strings or numbers. |
| `Query.isNull("name")` | Returns documents where attribute value is null. |
| `Query.isNotNull("name")` | Returns documents where attribute value is **not** null. |
| `Query.startsWith("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query.endsWith("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query.contains("ingredients", ['apple', 'banana'])` | Returns documents if a the array attribute contains the specified elements. |
| `Query.contains("name", "Tom")` | Returns documents if a string attributes is like the pattern specified. |
| `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query.orderDesc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.orderAsc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.limit(25)` | Limits the number of results returned by the query. Used for [pagination](/docs/products/databases/pagination). If the limit query is not used, the limit defaults to 25 results. |
| `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorAfter("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
{% /tabsitem %}
{% tabsitem #dotnet title=".NET" %}
| Example | Description |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `Query.select(["name", "title"])` | Select which attributes should be returned from a document. |
| `Query.or([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches any of the nested sub-queries in the array passed in. |
| `Query.equal("title", ["Iron Man"])` | Returns document if attribute is equal to any value in the provided array. |
| `Query.notEqual("title", ["Iron Man"])` | Returns document if attribute is not equal to any value in the provided array. |
| `Query.lessThan("score", 10)` | Returns document if attribute is less than the provided value. |
| `Query.lessThanEqual("score", 10)` | Returns document if attribute is less than or equal to the provided value. |
| `Query.greaterThan("score", 10)` | Returns document if attribute is greater than the provided value. |
| `Query.greaterThanEqual("score", 10)` | Returns document if attribute is greater than or equal to the provided value. |
| `Query.between("price", 5, 10)` | Returns document if attribute value falls between the two values. The boundary values are inclusive and can be strings or numbers. |
| `Query.isNull("name")` | Returns documents where attribute value is null. |
| `Query.isNotNull("name")` | Returns documents where attribute value is **not** null. |
| `Query.startsWith("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query.endsWith("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query.contains("ingredients", ['apple', 'banana'])` | Returns documents if a the array attribute contains the specified elements. |
| `Query.contains("name", "Tom")` | Returns documents if a string attributes is like the pattern specified. |
| `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query.orderDesc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.orderAsc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.limit(25)` | Limits the number of results returned by the query. Used for [pagination](/docs/products/databases/pagination). If the limit query is not used, the limit defaults to 25 results. |
| `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorAfter("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
{% /tabsitem %}
{% tabsitem #kotlin title="Kotlin" %}
| Example | Description |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `Query.select(["name", "title"])` | Select which attributes should be returned from a document. |
| `Query.or([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches any of the nested sub-queries in the array passed in. |
| `Query.equal("title", ["Iron Man"])` | Returns document if attribute is equal to any value in the provided array. |
| `Query.notEqual("title", ["Iron Man"])` | Returns document if attribute is not equal to any value in the provided array. |
| `Query.lessThan("score", 10)` | Returns document if attribute is less than the provided value. |
| `Query.lessThanEqual("score", 10)` | Returns document if attribute is less than or equal to the provided value. |
| `Query.greaterThan("score", 10)` | Returns document if attribute is greater than the provided value. |
| `Query.greaterThanEqual("score", 10)` | Returns document if attribute is greater than or equal to the provided value. |
| `Query.between("price", 5, 10)` | Returns document if attribute value falls between the two values. The boundary values are inclusive and can be strings or numbers. |
| `Query.isNull("name")` | Returns documents where attribute value is null. |
| `Query.isNotNull("name")` | Returns documents where attribute value is **not** null. |
| `Query.startsWith("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query.endsWith("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query.contains("ingredients", ['apple', 'banana'])` | Returns documents if a the array attribute contains the specified elements. |
| `Query.contains("name", "Tom")` | Returns documents if a string attributes is like the pattern specified. |
| `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query.orderDesc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.orderAsc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.limit(25)` | Limits the number of results returned by the query. Used for [pagination](/docs/products/databases/pagination). If the limit query is not used, the limit defaults to 25 results. |
| `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorAfter("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
{% /tabsitem %}
{% tabsitem #java title="Java" %}
| Example | Description |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `Query.select(["name", "title"])` | Select which attributes should be returned from a document. |
| `Query.or([Query.lessThan(5), Query.greaterThan(10)])` | Returns document if it matches any of the nested sub-queries in the array passed in. |
| `Query.equal("title", ["Iron Man"])` | Returns document if attribute is equal to any value in the provided array. |
| `Query.notEqual("title", ["Iron Man"])` | Returns document if attribute is not equal to any value in the provided array. |
| `Query.lessThan("score", 10)` | Returns document if attribute is less than the provided value. |
| `Query.lessThanEqual("score", 10)` | Returns document if attribute is less than or equal to the provided value. |
| `Query.greaterThan("score", 10)` | Returns document if attribute is greater than the provided value. |
| `Query.greaterThanEqual("score", 10)` | Returns document if attribute is greater than or equal to the provided value. |
| `Query.between("price", 5, 10)` | Returns document if attribute value falls between the two values. The boundary values are inclusive and can be strings or numbers. |
| `Query.isNull("name")` | Returns documents where attribute value is null. |
| `Query.isNotNull("name")` | Returns documents where attribute value is **not** null. |
| `Query.startsWith("name", "Once upon a time")` | Returns documents if a string attributes starts with a substring. |
| `Query.endsWith("name", "happily ever after.")` | Returns documents if a string attributes ends with a substring. |
| `Query.contains("ingredients", ['apple', 'banana'])` | Returns documents if a the array attribute contains the specified elements. |
| `Query.contains("name", "Tom")` | Returns documents if a string attributes is like the pattern specified. |
| `Query.search("text", "key words")` | Searches string attributes for provided keywords. Requires a [full-text index](/docs/products/databases/collections#indexes) on queried attributes. |
| `Query.orderDesc("attribute")` | Orders results in descending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.orderAsc("attribute")` | Orders results in ascending order by attribute. Attribute must be indexed. Pass in an empty string to return in natural order. |
| `Query.limit(25)` | Limits the number of results returned by the query. Used for [pagination](/docs/products/databases/pagination). If the limit query is not used, the limit defaults to 25 results. |
| `Query.offset(0)` | Offset the results returned by skipping some of the results. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorAfter("62a7...f620")` | Places the cursor after the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
| `Query.cursorBefore("62a7...a600")` | Places the cursor before the specified resource ID. Used for [pagination](/docs/products/databases/pagination). |
{% /tabsitem %}
{% /tabs %}
# Building Queries {% #building-queries %}
@@ -40,7 +290,7 @@ Queries are passed to an endpoint through the `queries` parameter as an array of
Each query method is logically separated via `AND` operations. For `OR` operation, pass multiple values into the query method separated by commas.
For example `Query.equal('title', ['Avatar', 'Lord of the Rings'])` will fetch the movies `Avatar` or `Lord of the Rings`.
{% info title="Permissions required" %}
{% info title="Default pagination behavior" %}
By default, results are limited to the **first 25 items**.
You can change this through [pagination](/docs/products/databases/pagination).
{% /info %}
@@ -57,7 +307,7 @@ const client = new Client()
const databases = new Databases(client);
databases.listDocuments(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
[
Query.equal('title', ['Avatar', 'Lord of the Rings']),
@@ -77,7 +327,7 @@ void main() async {
try {
final documents = await databases.listDocuments(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
[
Query.equal('title', ['Avatar', 'Lord of the Rings']),
@@ -103,8 +353,8 @@ suspend fun main() {
try {
val documents = databases.listDocuments(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = listOf(
Query.equal("title", listOf("Avatar", "Lord of the Rings")),
Query.greaterThan("year", 1999)
@@ -128,8 +378,8 @@ func main() async throws {
do {
let documents = try await databases.listDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: [
Query.equal("title", ["Avatar", "Lord of the Rings"]),
Query.greaterThan("year", 1999)
@@ -143,8 +393,8 @@ func main() async throws {
```graphql
query {
databasesListDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]"
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>"
queries: ["equal(\"title\", [\"Avatar\", \"Lord of the Rings\"])", "greaterThan(\"year\", 1999)]
) {
total

View File

@@ -152,8 +152,8 @@ const client = new Client()
const databases = new Databases(client);
let promise = databases.listDocuments(
"[DATABASE_ID]"
"[COLLECTION_ID]",
"<DATABASE_ID>"
"<COLLECTION_ID>",
[
Query.equal('title', 'Hamlet')
]
@@ -177,7 +177,7 @@ void main() async {
try {
final documents = await databases.listDocuments(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
queries: [
Query.equal('title', 'Hamlet')
@@ -202,8 +202,8 @@ suspend fun main() {
try {
val documents = databases.listDocuments(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
queries = listOf(
Query.equal("title", "Hamlet")
)
@@ -226,8 +226,8 @@ func main() async throws{
do {
let documents = try await databases.listDocuments(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
queries: [
Query.equal("title", "Hamlet")
]

View File

@@ -1330,7 +1330,7 @@ export default async ({ req, res, log, error }) => {
try {
await databases.createDocument(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
ID.unique(),
{}
@@ -1363,7 +1363,7 @@ return function ($context) {
try {
$databases->createDocument(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
documentId: ID::unique(),
data: []
@@ -1395,8 +1395,8 @@ def main(context):
try:
databases.create_document(
database_id="[DATABASE_ID]",
collection_id="[COLLECTION_ID]",
database_id="<DATABASE_ID>",
collection_id="<COLLECTION_ID>",
document_id=ID.unique(),
data={}
)
@@ -1421,7 +1421,7 @@ def main(context)
begin
databases.create_document(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
documentId: ID.unique(),
data: {}
@@ -1447,8 +1447,8 @@ export default function ({req, res, error}: any){
try {
databases.createDocument(
"[DATABASE_ID]",
"[COLLECTION_ID]",
"<DATABASE_ID>",
"<COLLECTION_ID>",
ID.unique(),
{}
);
@@ -1475,7 +1475,7 @@ Future<dynamic> main(final context) async {
try {
await databases.createDocument(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
documentId: ID.unique(),
data: {}
@@ -1503,8 +1503,8 @@ func main(context: RuntimeContext) async throws -> RuntimeOutput {
do {
try await databases.createDocument(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: ID.unique(),
data: [:]
)
@@ -1536,8 +1536,8 @@ namespace DotNetRuntime
try {
await databases.CreateDocument(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: ID.Unique(),
data: new Dictionary<string, object>());
} catch (Exception e) {
@@ -1571,8 +1571,8 @@ class Main {
try {
databases.createDocument(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documentId = ID.unique()
data = mapOf()
)
@@ -1604,8 +1604,8 @@ public class Main {
try {
databases.createDocument(
"[DATABASE_ID]",
"[COLLECTION_ID]",
"<DATABASE_ID>",
"<COLLECTION_ID>",
ID.unique(),
new HashMap<>()
);
@@ -1647,7 +1647,7 @@ export default async ({ req, res, log }) => {
try {
await databases.createDocument(
'[DATABASE_ID]',
'<DATABASE_ID>',
'[COLLECTION_ID]',
ID.unique(),
{}
@@ -1685,7 +1685,7 @@ return function ($context) {
try {
$databases->createDocument(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
documentId: ID::unique(),
data: []
@@ -1721,8 +1721,8 @@ def main(context):
try:
databases.create_document(
database_id="[DATABASE_ID]",
collection_id="[COLLECTION_ID]",
database_id="<DATABASE_ID>",
collection_id="<COLLECTION_ID>",
document_id=ID.unique(),
data={}
)
@@ -1751,7 +1751,7 @@ def main(context)
databases = Appwrite::Databases.new(client)
begin
databases.create_document('[DATABASE_ID]', '[COLLECTION_ID]', Appwrite::ID.unique(), {})
databases.create_document('<DATABASE_ID>', '[COLLECTION_ID]', Appwrite::ID.unique(), {})
rescue Appwrite::Exception => e
context.error("Failed to create document: " + e.message)
return context.response.send("Failed to create document")
@@ -1778,8 +1778,8 @@ export default function ({req, res, error}: any){
try {
databases.createDocument(
"[DATABASE_ID]",
"[COLLECTION_ID]",
"<DATABASE_ID>",
"<COLLECTION_ID>",
ID.unique(),
{}
);
@@ -1811,7 +1811,7 @@ Future<dynamic> main(final context) async {
try {
await databases.createDocument(
databaseId: '[DATABASE_ID]',
databaseId: '<DATABASE_ID>',
collectionId: '[COLLECTION_ID]',
documentId: ID.unique(),
data: {}
@@ -1844,8 +1844,8 @@ func main(context: RuntimeContext) async throws -> RuntimeOutput {
do {
try await databases.createDocument(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: ID.unique()
data: [:]
)
@@ -1882,8 +1882,8 @@ namespace DotNetRuntime
try {
await databases.CreateDocument(
databaseId: "[DATABASE_ID]",
collectionId: "[COLLECTION_ID]",
databaseId: "<DATABASE_ID>",
collectionId: "<COLLECTION_ID>",
documentId: ID.Unique(),
data: new Dictionary<string, object>());
} catch (Exception e) {
@@ -1922,8 +1922,8 @@ class Main {
try {
databases.createDocument(
databaseId = "[DATABASE_ID]",
collectionId = "[COLLECTION_ID]",
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documentId = ID.unique(),
data = mapOf()
)
@@ -1960,8 +1960,8 @@ public class Main {
try {
databases.createDocument(
"[DATABASE_ID]",
"[COLLECTION_ID]",
"<DATABASE_ID>",
"<COLLECTION_ID>",
ID.unique(),
new HashMap<>()
);

View File

@@ -552,7 +552,7 @@ export default async function ({ req, res }) {
.setKey(process.env.APPWRITE_API_KEY);
const databases = new Databases(client);
const document = await databases.createDocument('[DATABASE_ID]', '[MESSAGES_COLLECTION_ID]', ID.unique(), message);
const document = await databases.createDocument('<DATABASE_ID>', '[MESSAGES_COLLECTION_ID]', ID.unique(), message);
return res.send("Message sent");
}
@@ -606,7 +606,7 @@ def main(context):
)
databases = Databases(client)
document = databases.create_document('[DATABASE_ID]', '[MESSAGES_COLLECTION_ID]', ID.unique(), message)
document = databases.create_document('<DATABASE_ID>', '[MESSAGES_COLLECTION_ID]', ID.unique(), message)
return context.res.send("Message sent")
@@ -661,7 +661,7 @@ return function ($context) {
->setKey(getenv('APPWRITE_API_KEY'));
$databases = new Databases($client);
$document = $databases->createDocument('[DATABASE_ID]', '[MESSAGES_COLLECTION_ID]', ID::unique(), $message);
$document = $databases->createDocument('<DATABASE_ID>', '[MESSAGES_COLLECTION_ID]', ID::unique(), $message);
return $context->res->send("Message sent");
}
@@ -711,7 +711,7 @@ def main(context)
.set_key(ENV['APPWRITE_API_KEY'])
databases = Appwrite::Database.new(client)
document = databases.create_document('[DATABASE_ID]', '[MESSAGES_COLLECTION_ID]', ID.unique(), message)
document = databases.create_document('<DATABASE_ID>', '[MESSAGES_COLLECTION_ID]', ID.unique(), message)
return context.res.send("Message sent")
end
@@ -761,7 +761,7 @@ Future main(final context) async {
.setKey(Platform.environment['APPWRITE_API_KEY']);
final databases = Database(client);
final document = await databases.createDocument('[DATABASE_ID]', '[MESSAGES_COLLECTION_ID]', ID.unique(), message);
final document = await databases.createDocument('<DATABASE_ID>', '[MESSAGES_COLLECTION_ID]', ID.unique(), message);
return context.res.send("Message sent");
}

View File

@@ -0,0 +1,115 @@
<script lang="ts">
import Docs from '$lib/layouts/Docs.svelte';
import Sidebar, { type NavParent, type NavTree } from '$lib/layouts/Sidebar.svelte';
const parent: NavParent = {
href: '/docs',
label: 'Messaging'
};
const navigation: NavTree = [
{
label: 'Getting started',
items: [
{
label: 'Overview',
href: '/docs/products/messaging'
},
]
},
{
label: 'Concepts',
items: [
{
label: 'Topics',
href: '/docs/products/messaging/topics'
},
{
label: 'Targets',
href: '/docs/products/messaging/targets'
},
{
label: 'Messages',
href: '/docs/products/messaging/messages'
},
]
},
{
label: 'Providers',
items: [
{
label: 'Push with APNs',
href: '/docs/products/messaging/apns'
},
{
label: 'Push with FCM',
href: '/docs/products/messaging/fcm'
},
{
label: 'Email with Mailgun',
href: '/docs/products/messaging/mailgun'
},
{
label: 'Email with Sendgrid',
href: '/docs/products/messaging/sendgrid'
},
{
label: 'Email with SMTP',
href: '/docs/products/messaging/smtp'
},
{
label: 'SMS with Twilio',
href: '/docs/products/messaging/twilio'
},
{
label: 'SMS with MSG91',
href: '/docs/products/messaging/msg91'
},
{
label: 'SMS with Telesign',
href: '/docs/products/messaging/telesign'
},
{
label: 'SMS with TextMagic',
href: '/docs/products/messaging/textmagic'
},
{
label: 'SMS with Vonage',
href: '/docs/products/messaging/vonage'
},
]
},
{
label: 'Journeys',
items: [
{
label: 'Send push notifications',
href: '/docs/products/messaging/send-push-notifications'
},
{
label: 'Send email messages',
href: '/docs/products/messaging/send-email-messages'
},
{
label: 'Send SMS messages',
href: '/docs/products/messaging/send-sms-messages'
},
]
},
{
label: 'References',
items: [
{
label: 'API reference',
href: '#'
},
]
},
];
</script>
<Docs variant="two-side-navs">
<Sidebar {navigation} {parent} />
<slot />
</Docs>

View File

@@ -0,0 +1,30 @@
---
layout: article
title: Messaging
description: Send push notifications, text, or emails to users or groups of users using your app.
back: /docs
---
Appwrite Messaging helps you communicate with your users through push notifications, emails, and SMS text messages.
Sending personalized communication for marketing, updates, and realtime alerts can increase user engagement and retention.
You can also use Appwrite Messaging to implement security checks and custom authentication flows.
{% only_dark %}
![Messaging overview](/images/docs/messaging/dark/message-overview.png)
{% /only_dark %}
{% only_light %}
![Messaging overview](/images/docs/messaging/message-overview.png)
{% /only_light %}
Explore what you can build with Appwrite Messaging.
{% cards %}
{% cards_item href="/docs/products/messaging/send-email-messages" title="Emails" %}
Send newsletters, invoices, promitions and other emails.
{% /cards_item %}
{% cards_item href="/docs/products/messaging/send-sms-messages" title="SMS messages" %}
Send SMS messages straight to your user's phone.
{% /cards_item %}
{% cards_item href="/docs/products/messaging/send-push-notifications" title="Push notifications" %}
Send push notifications to your user's devices.
{% /cards_item %}
{% /cards %}

View File

@@ -0,0 +1,351 @@
---
layout: article
title: Apple Push Notification service
description: Send push notifications to apps on Apple devices through Apple Push Notification service (APNs) using Appwrite Messaging.
back: /docs/
---
Apple Push Notification service (APNs) lets you send push notifications to Apple devices like macOS, iOS, tvOS, iPadOS, and watchOS devices.
APNs is a best-effort service, and will attempt to deliver you messages to your device when it's online and available again.
APNs will save the last [N] messages for [M] days and attempt delivery as soon as it's online.
{% section #add-provider step=1 title="Add provider" %}
To add APNs as a provider, navigate to **Messaging** > **Providers** > {% icon icon="plus" size="m" /%} **Add provider** > **Push notification**.
{% only_dark %}
![Add a FCM provider](/images/docs/messaging/providers/apns/dark/provider.png)
{% /only_dark %}
{% only_light %}
![Add a FCM provider](/images/docs/messaging/providers/apns/provider.png)
{% /only_light %}
Give your provider a name > choose **APNS** > click **Save and continue**.
The provider will be saved to your project, but not enabled until you complete its configuration.
{% /section %}
{% section #configure-provider step=2 title="Configure provider" %}
In the **Configure** step, you will need to provide details form your Apple developer account to connect your Appwrite project with your
Apple developer account.
You will need to provide the following information from the **Apple Developer Member Center**.
{% table %}
* Field name
*
---
* Team ID
*
Head to **Apple Developer Member Center** > **Membership details** > **Team ID**
{% only_dark %} ![Team ID](/images/docs/messaging/providers/apns/dark/team-id.png) {% /only_dark %} {% only_light %} ![Team ID](/images/docs/messaging/providers/apns/team-id.png) {% /only_light %}
---
* Bundle ID
*
Head to **Apple Developer Member Center** > **Program resources** > **Certificates, Identifiers & Profiles** > **Identifiers**
{% only_dark %} ![Bundle ID](/images/docs/messaging/providers/apns/dark/bundle-id.png) {% /only_dark %} {% only_light %} ![Bundle ID](/images/docs/messaging/providers/apns/bundle-id.png) {% /only_light %}
---
* Authentication key ID
*
Head to **Apple Developer Member Center** > **Program resources** > **Certificates, Identifiers & Profiles** > **Keys**. Click on your key to view details. The key needs **Apple Push Notification Service** enabled.
{% only_dark %} ![Authentication Key ID](/images/docs/messaging/providers/apns/dark/key-id.png) {% /only_dark %} {% only_light %} ![Authentication Key ID](/images/docs/messaging/providers/apns/key-id.png) {% /only_light %}
---
* Authentication key (.p8 file)
*
Head to **Apple Developer Member Center** > **Program resources** > **Certificates, Identifiers & Profiles** > **Keys**. Create a key and give it a name. Enable the Apple Push Notifications service (APNS), and register your key. The key needs **Apple Push Notification Service** enabled.
{% only_dark %} ![Authentication Key](/images/docs/messaging/providers/apns/dark/authentication-key.png) {% /only_dark %} {% only_light %} ![Authentication Key](/images/docs/messaging/providers/apns/authentication-key.png) {% /only_light %}
{% /table %}
After adding the following details, click **Save and continue** to enable the provider.
{% /section %}
{% section #configure-app step=3 title="Configure app" %}
Some additional configuration is required to enable push notifications in your iOS app.
Add push notification capability to your app by clicking your root-level app in XCode > **Signing & Capabilities** > {% icon icon="plus" size="m" /%} Capabilities > Search for **Push Notifications**.
{% only_dark %} ![Enable PN on Xcode](/images/docs/messaging/providers/apns/dark/xcode-enable-pn.png) {% /only_dark %} {% only_light %} ![Enable PN on Xcode](/images/docs/messaging/providers/apns/xcode-enable-pn.png) {% /only_light %}
{% /section %}
{% section #test-provider step=4 title="Test provider" %}
Push notification requires special handling on the client side. Follow the [Send push notification](/docs/products/messaging/send-push-notifications) flow to test your provider.
{% /section %}
{% section #manage-provider step=4 title="Manage provider" %}
{% tabs %}
{% tabsitem #console title="Console" %}
You can update or delete a provider in the Appwrite Console.
Navigate to **Messaging** > **Providers** > click your provider.
In the settings, you can update a provider's configuration or delete the provider.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To update or delete providers programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateAPNSProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[AUTH_KEY]', // authKey (optional)
'[AUTH_KEY_ID]', // authKeyId (optional)
'[TEAM_ID]', // teamId (optional)
'[BUNDLE_ID]' // bundleId (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateAPNSProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[AUTH_KEY]', // authKey (optional)
'[AUTH_KEY_ID]', // authKeyId (optional)
'[TEAM_ID]', // teamId (optional)
'[BUNDLE_ID]' // bundleId (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->updateAPNSProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
authKey: '[AUTH_KEY]', // optional
authKeyId: '[AUTH_KEY_ID]', // optional
teamId: '[TEAM_ID]', // optional
bundleId: '[BUNDLE_ID]' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.update_apns_provider(
provider_id = '[PROVIDER_ID]',
name = '[NAME]', # optional
enabled = False, # optional
auth_key = '[AUTH_KEY]', # optional
auth_key_id = '[AUTH_KEY_ID]', # optional
team_id = '[TEAM_ID]', # optional
bundle_id = '[BUNDLE_ID]' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.update_apns_provider(
provider_id: '[PROVIDER_ID]',
name: '[NAME]', # optional
enabled: false, # optional
auth_key: '[AUTH_KEY]', # optional
auth_key_id: '[AUTH_KEY_ID]', # optional
team_id: '[TEAM_ID]', # optional
bundle_id: '[BUNDLE_ID]' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Provider result = await messaging.UpdateAPNSProvider(
providerId: "[PROVIDER_ID]"
name: "[NAME]" // optional
enabled: false // optional
authKey: "[AUTH_KEY]" // optional
authKeyId: "[AUTH_KEY_ID]" // optional
teamId: "[TEAM_ID]" // optional
bundleId: "[BUNDLE_ID]"); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.updateAPNSProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
authKey: '[AUTH_KEY]', // optional
authKeyId: '[AUTH_KEY_ID]', // optional
teamId: '[TEAM_ID]', // optional
bundleId: '[BUNDLE_ID]', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateAPNSProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[AUTH_KEY]", // authKey (optional)
"[AUTH_KEY_ID]", // authKeyId (optional)
"[TEAM_ID]", // teamId (optional)
"[BUNDLE_ID]" // bundleId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateAPNSProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[AUTH_KEY]", // authKey (optional)
"[AUTH_KEY_ID]", // authKeyId (optional)
"[TEAM_ID]", // teamId (optional)
"[BUNDLE_ID]" // bundleId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let provider = try await messaging.updateAPNSProvider(
providerId: "[PROVIDER_ID]",
name: "[NAME]", // optional
enabled: xfalse, // optional
authKey: "[AUTH_KEY]", // optional
authKeyId: "[AUTH_KEY_ID]", // optional
teamId: "[TEAM_ID]", // optional
bundleId: "[BUNDLE_ID]" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

View File

@@ -0,0 +1,342 @@
---
layout: article
title: Firebase Cloud Messaging
description: Send push notifications to Android, Apple, or Web app with Firebase Cloud Messaging (FCM).
back: /docs/
---
Firebase Cloud Messaging (FCM) lets you send push notifications to your iOS, Android, and web apps through Appwrite Messaging.
Before you can deliver messages, you must connect to a messaging provider.
{% section #add-provider step=1 title="Add provider" %}
To add FCM as a provider, navigate to **Messaging** > **Providers** > {% icon icon="plus" size="m" /%} **Add provider** > **Push notification**.
{% only_dark %}
![Add a FCM provider](/images/docs/messaging/providers/fcm/dark/provider.png)
{% /only_dark %}
{% only_light %}
![Add a FCM provider](/images/docs/messaging/providers/fcm/provider.png)
{% /only_light %}
Give your provider a name > choose **FCM** > click **Save and continue**.
The provider will be saved to your project, but not enabled until you complete its configuration.
{% /section %}
{% section #configure-provider step=2 title="Configure provider" %}
In the **Configure** step, you will need to provide details form your Firebase console to connect your Appwrite project.
You will need to provide the following information from the **Firebase console**.
{% info title="Enable FCM" %}
FCM must be enabled on your Firebase project.
Head to Firebase console -> Settings -> Project settings -> Cloud Messaging.
If FCM is disabled, click the three-dots menu and open the link. On the following page, click **Enable** (it might take a few minutes for the action to complete).
{% /info %}
{% table %}
* Field name
*
---
* Server key (.json file)
*
Head to **Project settings** > **Service accounts** > **Generate new private key**.
{% only_dark %} ![FCM admin key](/images/docs/messaging/providers/fcm/dark/admin-key.png) {% /only_dark %} {% only_light %} ![FCM admin key](/images/docs/messaging/providers/fcm/admin-key.png) {% /only_light %}
{% /table %}
After adding the following details, click **Save and continue** to enable the provider.
{% /section %}
{% section #configure-app step=3 title="Configure app" %}
Some additional configuration is required to enable push notifications in your mobile app.
{% tabs %}
{% tabsitem #fcm-android title="Android with FCM" %}
1. Install the `com.google.firebase:firebase-messaging` Firebase SDK.
1. In your Firebase console, navigate to **Settings** > **General** > **Your apps** > add an **Android** app.
1. Register and download your `google-services.json` config file.
1. Add `google-services.json` at the root of your project.
1. Add Google Services class path to your app-level Gradle dependencies block `"com.google.gms:google-services:4.4.0"`.
1. Add Google Services plugin to your app-level Gradle in the plugins block as `"com.google.gms.google-services"`.
1. Add notification handler service to `AndroidManifest.xml` inside the application tag, alongisde other activities.
```groovy
<service android:name="io.appwrite.NotificationHandler" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
```
{% /tabsitem %}
{% tabsitem #fcm-ios title="iOS with FCM" %}
1. In your Firebase console, navigate to **Settings** > **General** > **Your apps** > add an **iOS** app.
1. Register and download your `GoogleService-Info.plist` and add it to the root of your project.
1. Head to **Apple Developer Member Center** > **Program resources** > **Certificates, Identifiers & Profiles** > **Keys**. The key needs **Apple Push Notification Service** enabled.
1. Create a new key, note down the key ID and download your key.
1. In Firebase console, go to *Settings** > **Cloud Messaging** > **APNs authentication key** > click **Upload**. Upload your key here.
1. Add push notification capability to your app by clicking your root-level app in XCode > **Signing & Capabilities** > {% icon icon="plus" size="m" /%} Capabilities > Search for **Push Notifications**.
1. If using SwiftUI, disable swizzling by setting `FirebaseAppDelegateProxyEnabled` to `NO` in your `Info.plist`.
{% /tabsitem %}
{% /tabs %}
{% /section %}
{% section #test-provider step=4 title="Test provider" %}
Push notification requires special handling on the client side. Follow the [Send push notification](/docs/products/messaging/send-push-notifications) flow to test your provider.
{% /section %}
{% section #manage-provider step=4 title="Manage provider" %}
{% tabs %}
{% tabsitem #console title="Console" %}
You can update or delete a provider in the Appwrite Console.
Navigate to **Messaging** > **Providers** > click your provider.
In the settings, you can update a provider's configuration or delete the provider.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To update or delete providers programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateFCMProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
{} // serviceAccountJSON (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateFCMProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
{} // serviceAccountJSON (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->updateFCMProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
serviceAccountJSON: [] // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.update_fcm_provider(
provider_id = '[PROVIDER_ID]',
name = '[NAME]', # optional
enabled = False, # optional
service_account_json = {} # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.update_fcm_provider(
provider_id: '[PROVIDER_ID]',
name: '[NAME]', # optional
enabled: false, # optional
service_account_json: {} # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Provider result = await messaging.UpdateFCMProvider(
providerId: "[PROVIDER_ID]"
name: "[NAME]" // optional
enabled: false // optional
serviceAccountJSON: [object]); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.updateFCMProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
serviceAccountJSON: {}, // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateFCMProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
mapOf( "a" to "b" ) // serviceAccountJSON (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateFCMProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
mapOf( "a" to "b" ) // serviceAccountJSON (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let provider = try await messaging.updateFCMProvider(
providerId: "[PROVIDER_ID]",
name: "[NAME]", // optional
enabled: xfalse, // optional
serviceAccountJSON: [:] // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

View File

@@ -0,0 +1,609 @@
---
layout: article
title: Mailgun
description: Send emails to your Appwrite users using Mailgun and Appwrite Messaging.
back: /docs/
---
Mailgun lets you send customized email messages to your users.
These emails can be sent immediately or scheduled.
You can send emails for purposes like reminders, promotions, announcements, and even custom authentication flows.
{% section #add-provider step=1 title="Add provider" %}
To add Mailgun as a provider, navigate to **Messaging** > **Providers** > {% icon icon="plus" size="m" /%} **Add provider** > **Email**.
{% only_dark %}
![Add a SMTP provider](/images/docs/messaging/providers/mailgun/dark/add-mailgun.png)
{% /only_dark %}
{% only_light %}
![Add a SMTP provider](/images/docs/messaging/providers/mailgun/add-mailgun.png)
{% /only_light %}
Give your provider a name > choose **Mailgun** > click **Save and continue**.
The provider will be saved to your project, but not enabled until you complete its configuration.
{% /section %}
{% section #configure-provider step=2 title="Configure provider" %}
In the **Configure** step, you will need to provide details form your Mailgun dashboard to connect your Appwrite project.
{% only_dark %}
![Configure SMTP provider](/images/docs/messaging/providers/mailgun/dark/configure-mailgun.png)
{% /only_dark %}
{% only_light %}
![Configure SMTP provider](/images/docs/messaging/providers/mailgun/configure-mailgun.png)
{% /only_light %}
You will need to provide the following information from your **Mailgun dashboard**.
{% table %}
* Field name
*
---
* API key
* Head to Profile -> API Security -> Add new key.
---
* Domain
* Head to Sending -> Domains -> Add new domain.
Follow [Mailgun's instructions](https://help.mailgun.com/hc/en-us/articles/360026833053-Domain-Verification-Walkthrough) to verify the domain name.
---
* EU region
* Enable the EU region setting if your domain is within the European Union.
---
* Sender email
* The provider sends emails from this sender email. The sender email needs to be an email under the configured domain.
---
* Sender name
* The sender name that appears in the emails sent from this provider.
---
* Reply-to email
* The reply-to email that appears in the emails sent from this provider. The reply-to email needs to be an email under the configured domain.
---
* Reply-to name
* The reply-to name that appears in the emails sent from this provider.
{% /table %}
After adding the following details, click **Save and continue** to enable the provider.
{% /section %}
{% section #test-provider step=3 title="Test provider" %}
Before sending your first message,
make sure you've configured [a topic](/docs/products/messaging/topics) and [a target](/docs/products/messaging/targets) to send messages to.
{% tabs %}
{% tabsitem #console title="Console" %}
To send a test message, navigate to **Messaging** > **Messages** > {% icon icon="plus" size="m" /%} **Create message** > **Email**.
{% only_dark %}
![Create email message](/images/docs/messaging/messages/dark/create-email-message.png)
{% /only_dark %}
{% only_light %}
![Create email message](/images/docs/messaging/messages/create-email-message.png)
{% /only_light %}
Add your message and in the targets step, select one of your test targets. Set the schedule to **Now** and click **Send**.
Verify that you can receive the message in your inbox. If not, check for logs in the Appwrite Console or in your provider's logs.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To send a message programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
const promise = messaging.createEmail('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>');
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
let promise = messaging.createEmail('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>');
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<PROJECT_ID>') // Your project ID
->setKey('<API_KEY>') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->createEmail('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>');
```
```python
from appwrite.client import Client
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
)
messaging = Messaging(client)
result = messaging.create_email('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>')
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
messaging = Messaging.new(client)
response = messaging.create_email(message_id: '<MESSAGE_ID>', subject: '<SUBJECT>', content: '<CONTENT>')
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
using Appwrite.Enums;
using Appwrite.Enums;
using Appwrite.Enums;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<PROJECT_ID>") // Your project ID
.SetKey("<API_KEY>"); // Your secret API key
var messaging = new Messaging(client);
Message result = await messaging.CreateEmail(
messageId: "<MESSAGE_ID>",
subject: "<SUBJECT>",
content: "<CONTENT>");
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
Future result = messaging.createEmail(
messageId:'<MESSAGE_ID>' ,
subject:'<SUBJECT>' ,
content:'<CONTENT>' ,
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Messaging
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
val messaging = Messaging(client)
val response = messaging.createEmail(
messageId = "<MESSAGE_ID>",
subject = "<SUBJECT>",
content = "<CONTENT>",
)
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createEmail(
"<MESSAGE_ID>",
"<SUBJECT>",
"<CONTENT>",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
let messaging = Messaging(client)
let message = try await messaging.createEmail(
messageId: "<MESSAGE_ID>",
subject: "<SUBJECT>",
content: "<CONTENT>"
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
You can follow the [Send email messages](/docs/products/messaging/send-push-notifications) journey to send your first push notification and test your provider.
{% /section %}
{% section #manage-provider step=4 title="Manage provider" %}
{% tabs %}
{% tabsitem #console title="Console" %}
You can update or delete a provider in the Appwrite Console.
Navigate to **Messaging** > **Providers** > click your provider.
In the settings, you can update a provider's configuration or delete the provider.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To update or delete providers programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
// update provider
messaging.updateSendgridProvider(
'<PROVIDER_ID>',
'<PROVIDER_NAME>',
'<API_KEY>',
'<DOMAIN>',
'<IS_EU_REGION?>',
'<SENDER_NAME>',
'<SENDER_EMAIL>',
'<REPLY_TO_NAME>',
'<REPLY_TO_EMAIL>',
'<ENABLED?>',
).then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
// delete provider
messaging.deleteProvider('<PROVIDER_ID>')
.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
// update provider
messaging.updateSendgridProvider(
'<PROVIDER_ID>',
'<PROVIDER_NAME>',
'<API_KEY>',
'<DOMAIN>',
'<IS_EU_REGION?>',
'<SENDER_NAME>',
'<SENDER_EMAIL>',
'<REPLY_TO_NAME>',
'<REPLY_TO_EMAIL>',
'<ENABLED?>',
).then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
// delete provider
messaging.deleteProvider('<PROVIDER_ID>')
.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<PROJECT_ID>') // Your project ID
->setKey('<API_KEY>') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->updateSendgridProvider(
'<PROVIDER_ID>',
'<PROVIDER_NAME>',
'<API_KEY>',
'<DOMAIN>',
'<IS_EU_REGION?>',
'<SENDER_NAME>',
'<SENDER_EMAIL>',
'<REPLY_TO_NAME>',
'<REPLY_TO_EMAIL>',
'<ENABLED?>',
);
```
```python
from appwrite.client import Client
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
)
messaging = Messaging(client)
result = messaging.update_sendgrid_provider(
'<PROVIDER_ID>',
'<PROVIDER_NAME>',
'<API_KEY>',
'<DOMAIN>',
'<IS_EU_REGION?>',
'<SENDER_NAME>',
'<SENDER_EMAIL>',
'<REPLY_TO_NAME>',
'<REPLY_TO_EMAIL>',
'<ENABLED?>',
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
messaging = Messaging.new(client)
response = messaging.update_sendgrid_provider(
provider_id: "<PROVIDER_ID>",
name: "<PROVIDER_NAME>",
api_key: "<API_KEY>",
domain: "<DOMAIN>",
isEuRegion: "<IS_EU_REGION?>",
from_name: "<SENDER_NAME>",
from_email: "<SENDER_EMAIL>",
reply_to_name: "<REPLY_TO_NAME>",
reply_to_email: "<REPLY_TO_EMAIL>",
enabled: "<ENABLED?>",
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
using Appwrite.Enums;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<PROJECT_ID>") // Your project ID
.SetKey("<API_KEY>"); // Your secret API key
var messaging = new Messaging(client);
Provider result = await messaging.UpdateSendgridProvider(
providerId: "<PROVIDER_ID>",
name: "<PROVIDER_NAME>",
apiKey: "<API_KEY>",
domain: "<DOMAIN>",
isEuRegion: "<IS_EU_REGION?>",
fromName: "<SENDER_NAME>",
fromEmail: "<SENDER_EMAIL>",
replyToName: "<REPLY_TO_NAME>",
replyToEmail: "<REPLY_TO_EMAIL>",
enabled: "<ENABLED?>",
);
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
Future result = messaging.updateSendgridProvider(
providerId: "<PROVIDER_ID>",
name: "<PROVIDER_NAME>",
apiKey: "<API_KEY>",
domain: "<DOMAIN>",
isEuRegion: "<IS_EU_REGION?>",
fromName: "<SENDER_NAME>",
fromEmail: "<SENDER_EMAIL>",
replyToName: "<REPLY_TO_NAME>",
replyToEmail: "<REPLY_TO_EMAIL>",
enabled: "<ENABLED?>",
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Messaging
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
val messaging = Messaging(client)
val response = messaging.updateSendgridProvider(
providerId = "<PROVIDER_ID>",
name = "<PROVIDER_NAME>",
apiKey = "<API_KEY>",
domain = "<DOMAIN>",
isEuRegion = "<IS_EU_REGION?>",
fromName = "<SENDER_NAME>",
fromEmail = "<SENDER_EMAIL>",
replyToName = "<REPLY_TO_NAME>",
replyToEmail = "<REPLY_TO_EMAIL>",
enabled = "<ENABLED?>",
)
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateSendgridProvider(
"<PROVIDER_ID>",
"<PROVIDER_NAME>",
"<API_KEY>",
"<DOMAIN>",
"<IS_EU_REGION?>",
"<SENDER_NAME>",
"<SENDER_EMAIL>",
"<REPLY_TO_NAME>",
"<REPLY_TO_EMAIL>",
"<ENABLED?>",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
let messaging = Messaging(client)
let provider = try await messaging.updateSendgridProvider(
providerId: "<PROVIDER_ID>",
name: "<PROVIDER_NAME>",
apiKey: "<API_KEY>",
domain: "<DOMAIN>",
isEuRegion: "<IS_EU_REGION?>",
fromName: "<SENDER_NAME>",
fromEmail: "<SENDER_EMAIL>",
replyToName: "<REPLY_TO_NAME>",
replyToEmail: "<REPLY_TO_EMAIL>",
enabled: "<ENABLED?>",
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,615 @@
---
layout: article
title: MSG91
description: Send SMS messages to your Appwrite users using MSG91 and Appwrite Messaging.
back: /docs/
---
MSG91 lets you send customized SMS messages to your users.
These SMS messages can be sent immediately or scheduled.
You can send SMS messages for purposes like reminders, promotions, announcements, and even custom authentication flows.
{% section #add-provider step=1 title="Add provider" %}
To add MSG91 as a provider, navigate to **Messaging** > **Providers** > {% icon icon="plus" size="m" /%} **Add provider** > **SMS**.
{% only_dark %}
![Add a MSG91 provider](/images/docs/messaging/providers/msg91/dark/provider.png)
{% /only_dark %}
{% only_light %}
![Add a MSG91 provider](/images/docs/messaging/providers/msg91/provider.png)
{% /only_light %}
Give your provider a name > choose **MSG91** > click **Save and continue**.
The provider will be saved to your project, but not enabled until you complete its configuration.
{% /section %}
{% section #configure-provider step=2 title="Configure provider" %}
In the **Configure** step, you will need to provide details form your MSG91 dashboard to connect your Appwrite project.
You will need to provide the following information from your **MSG91 dashboard**.
{% table %}
* Field name
*
---
* Auth key
* Click to open the Username dropdown > **Authkey** > **Verify your mobile number** > **Create Authkey**.
---
* Sender ID
* Head to MSG91 dashboard > **SMS** > **Sender ID** > **Create sender ID**.
---
* Sender number
*
{% /table %}
After adding the following details, click **Save and continue** to enable the provider.
{% /section %}
{% section #test-provider step=3 title="Test provider" %}
Before sending your first message,
make sure you've configured [a topic](/docs/products/messaging/topics) and [a target](/docs/products/messaging/targets) to send messages to.
{% tabs %}
{% tabsitem #console title="Console" %}
To send a test message, navigate to **Messaging** > **Messages** > {% icon icon="plus" size="m" /%} **Create message** > **SMS**.
{% only_dark %}
![Create email message](/images/docs/messaging/messages/dark/create-email-message.png)
{% /only_dark %}
{% only_light %}
![Create email message](/images/docs/messaging/messages/create-email-message.png)
{% /only_light %}
Add your message and in the targets step, select one of your test targets. Set the schedule to **Now** and click **Send**.
Verify that you can receive the message in your inbox. If not
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To send a message programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createSMS(
'[MESSAGE_ID]', // messageId
'[CONTENT]', // content
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createSMS(
'[MESSAGE_ID]', // messageId
'[CONTENT]', // content
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->createSMS(
messageId: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], // optional
users: [], // optional
targets: [], // optional
status: 'draft', // optional
scheduledAt: '' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.create_sms(
message_id = '[MESSAGE_ID]',
content = '[CONTENT]',
topics = [], # optional
users = [], # optional
targets = [], # optional
status = 'draft', # optional
scheduled_at = '' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.create_sms(
message_id: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], # optional
users: [], # optional
targets: [], # optional
status: 'draft', # optional
scheduled_at: '' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Message result = await messaging.CreateSMS(
messageId: "[MESSAGE_ID]",
content: "[CONTENT]"
topics: new List<string> {} // optional
users: new List<string> {} // optional
targets: new List<string> {} // optional
status: "draft" // optional
scheduledAt: ""); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.createSMS(
messageId: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], // optional
users: [], // optional
targets: [], // optional
status: 'draft', // optional
scheduledAt: '', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createSMS(
"[MESSAGE_ID]", // messageId
"[CONTENT]", // content
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createSMS(
"[MESSAGE_ID]", // messageId
"[CONTENT]", // content
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let message = try await messaging.createSMS(
messageId: "[MESSAGE_ID]",
content: "[CONTENT]",
topics: [], // optional
users: [], // optional
targets: [], // optional
status: "draft", // optional
scheduledAt: "" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
You can follow the [Send email messages](/docs/products/messaging/send-sms-messages) journey to send your first push notification and test your provider.
{% /section %}
{% section #manage-provider step=4 title="Manage provider" %}
{% tabs %}
{% tabsitem #console title="Console" %}
You can update or delete a provider in the Appwrite Console.
Navigate to **Messaging** > **Providers** > click your provider.
In the settings, you can update a provider's configuration or delete the provider.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To update or delete providers programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateMsg91Provider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[SENDER_ID]', // senderId (optional)
'[AUTH_KEY]', // authKey (optional)
'[FROM]' // from (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateMsg91Provider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[SENDER_ID]', // senderId (optional)
'[AUTH_KEY]', // authKey (optional)
'[FROM]' // from (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->updateMsg91Provider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
senderId: '[SENDER_ID]', // optional
authKey: '[AUTH_KEY]', // optional
from: '[FROM]' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.update_msg91_provider(
provider_id = '[PROVIDER_ID]',
name = '[NAME]', # optional
enabled = False, # optional
sender_id = '[SENDER_ID]', # optional
auth_key = '[AUTH_KEY]', # optional
from = '[FROM]' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.update_msg91_provider(
provider_id: '[PROVIDER_ID]',
name: '[NAME]', # optional
enabled: false, # optional
sender_id: '[SENDER_ID]', # optional
auth_key: '[AUTH_KEY]', # optional
from: '[FROM]' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Provider result = await messaging.UpdateMsg91Provider(
providerId: "[PROVIDER_ID]"
name: "[NAME]" // optional
enabled: false // optional
senderId: "[SENDER_ID]" // optional
authKey: "[AUTH_KEY]" // optional
from: "[FROM]"); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.updateMsg91Provider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
senderId: '[SENDER_ID]', // optional
authKey: '[AUTH_KEY]', // optional
from: '[FROM]', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateMsg91Provider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[SENDER_ID]", // senderId (optional)
"[AUTH_KEY]", // authKey (optional)
"[FROM]" // from (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateMsg91Provider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[SENDER_ID]", // senderId (optional)
"[AUTH_KEY]", // authKey (optional)
"[FROM]" // from (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let provider = try await messaging.updateMsg91Provider(
providerId: "[PROVIDER_ID]",
name: "[NAME]", // optional
enabled: xfalse, // optional
senderId: "[SENDER_ID]", // optional
authKey: "[AUTH_KEY]", // optional
from: "[FROM]" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,843 @@
---
layout: article
title: Send push notification
description: Send push notification to your users using Appwrite Messaging.
---
You can send, schedule, and manage push notifications to your apps using Appwrite Messaging.
Push notifications can be used to deliver new message notifications, app updates, promotional offers,
and other messages straight to your user's devices.
{% section #add-provider step=1 title="Add provider" %}
Push notifications must be sent through third-party providers, like Apple Push Notification service and Firebase Cloud Messaging.
The push notification APIs for Apple and Android devices can only be accessed through these services.
You must configure these services before you can send your first push notification.
{% cards %}
{% cards_item href="/docs/products/messaging/apns" title="APNS" icon="icon-apple" %}
Configure APNs for push notification to Apple devices.
{% /cards_item %}
{% cards_item href="/docs/products/messaging/fcm" title="FCM" icon="icon-firebase" %}
Configure FCM for push notification to Android and Apple devices.
{% /cards_item %}
{% /cards %}
{% /section %}
{% section #add-targets step=2 title="Add targets" %}
Before sending your first push notification, your application must register itself for push notification,
then provide the device token to Appwrite.
{% tabs %}
{% tabsitem #apple-apns title="APNs for Apple" %}
First, enable push notification in your app.
Add push notification capability to your app by clicking your root-level app in XCode > **Signing & Capabilities** > {% icon icon="plus" size="m" /%} Capabilities > Search for **Push Notifications**.
{% only_dark %} ![Authentication Key](/images/docs/messaging/providers/apns/dark/xcode-enable-pn.png) {% /only_dark %} {% only_light %} ![Authentication Key](/images/docs/messaging/providers/apns/xcode-enable-pn.png) {% /only_light %}
First, register for remote notifications in your app delegate's `application(_:didFinishLaunchingWithOptions:)` method.
```swift
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
) -> Bool {
// Register for remote notifications
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: { granted, error in
DispatchQueue.main.async {
if granted {
application.registerForRemoteNotifications()
}
}
}
)
return true
}
```
Next, create a handler for when the app receives the push notification device token.
```swift
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
// register device
var token = deviceToken.map { String(format: "%.2hhx", $0) }.joined()
// Save the token to be used later
UserDefaults.standard.set(token, forKey: "apnsToken")
}
```
Since the token is saved in `UserDefaults`, you can access it from anywhere in your app.
With this saved `apnsToken`, you can create a push target with Appwrite when the user logs in.
Each push target is associated with an account, heres an example with a email password login.
The same logic applies to all types of login methods.
```swift
func login() async {
do {
let session = try await account.createEmailPasswordSession(
email: username,
password: password
)
guard let token = UserDefaults.standard.string(forKey: "apnsToken") else {
return
}
guard let target = try? await account.createPushTarget(
targetId: ID.unique(),
identifier: token
) else {
return
}
UserDefaults.standard.set(target.id, forKey: "targetId")
DispatchQueue.main.async {
self.response = String(describing: session.toMap())
}
} catch {
DispatchQueue.main.async {
self.response = error.localizedDescription
}
}
}
```
{% /tabsitem %}
{% tabsitem #android-fcm title="FCM for Android" %}
Before you can send push notifications using FCM, make sure you'd followed the steps to
[Add Firebase to your Android project](https://firebase.google.com/docs/android/setup).
After adding Firebase to your Android project and adding the `google-services.json` to your project,
initialize Firebase in your main activity and fetch the FCM registration token.
```kotlin
class MainActivity : AppCompatActivity() {
override fun onCreate() {
// ... other logic
// Initialize Firebase
FirebaseApp.initializeApp(this)
// Set the FCM token
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w(TAG, "Fetching FCM registration token failed", task.exception)
return@OnCompleteListener
}
// Get new FCM registration token and save it in prefs to be used later.
val token = task.result
val prefs = getSharedPreferences("example", MODE_PRIVATE)
prefs.edit().putString("fcmToken", token).apply()
})
}
}
```
Appwrite's push targets are associated with accounts.
Typically, you would create a push target when the user logs in.
For example, when the user logs in with email and password, your app
can register itself as a target after handling the login.
```kotlin
fun onLogin(
email: String,
password: String,
token: String?,
) {
viewModelScope.launch {
try {
// Log in the user
val session = account.createEmailPasswordSession(
email,
password
)
// If a token exists, register a push target with Appwrite.
if (token != null) {
val target = account.createPushTarget(ID.unique(), token)
_target.postValue(Event(target))
}
_response.postValue(Event(session.toJson()))
} catch (e: AppwriteException) {
_error.postValue(Event(e))
}
}
}
```
The FCM token that we defined in `sharedPreferenes` will be passed into the `onLogin` handler
to create the push target.
```kotlin
binding.login.setOnClickListener{
viewModel.onLogin(
binding.email.text.toString(),
binding.password.text.toString(),
context
?.getSharedPreferences("example", Context.MODE_PRIVATE)
?.getString("fcmToken", null) ?: null
)
}
```
Lastly, because FCM push tokens can change, we need to add a service to handle FCM token
refreshes and update the target with Appwrite Messaging.
Create a new service that extends `FirebaseMessagingService` which handles the event where
the FCM token is updated.
```kotlin
class MessagingService : FirebaseMessagingService() {
companion object {
var account: Account? = null
}
// This is called when FCM token is updated.
override fun onNewToken(token: String) {
super.onNewToken(token)
val prefs = getSharedPreferences("example", MODE_PRIVATE)
prefs.edit().putString("fcmToken", token).apply()
if (account == null) {
return
}
val targetId = prefs.getString("targetId", null)
runBlocking {
if (targetId == null) {
val target = account!!.createPushTarget(ID.unique(), token)
prefs.edit().putString("targetId", target.id).apply()
} else {
account!!.updatePushTarget(targetId, token)
}
}
}
}
```
In your `AndroidManifest.xml`, register this new service.
```xml
<service android:name="io.appwrite.NotificationHandler" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
```
{% /tabsitem %}
{% tabsitem #apple-fcm title="FCM for Apple" %}
Before you can send push notifications using FCM, make sure you'd followed the steps to
[Add Firebase to your iOS project](https://firebase.google.com/docs/ios/setup).
After adding Firebase to your iOS project and adding the `GoogleService-Info.plist` to the root of your project.
Next, add your APNs key to Firebase.
1. Head to **Apple Developer Member Center** > **Program resources** > **Certificates, Identifiers & Profiles** > **Keys**. The key needs **Apple Push Notification Service** enabled.
1. Create a new key, note down the key ID and download your key.
1. In Firebase console, go to *Settings** > **Cloud Messaging** > **APNs authentication key** > click **Upload**. Upload your key here.
1. Add push notification capability to your app by clicking your root-level app in XCode > **Signing & Capabilities** > {% icon icon="plus" size="m" /%} Capabilities > Search for **Push Notifications**.
1. If using SwiftUI, disable swizzling by setting `FirebaseAppDelegateProxyEnabled` to `NO` in your `Info.plist`.
Initialize Firebase in your app delegate's `application(_:didFinishLaunchingWithOptions:)` method,
implement the messaging delegate protocol, and register for remote notifications.
```swift
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
) -> Bool {
// initialize Firebase
FirebaseApp.configure()
// Set the messaging delegate
Messaging.messaging().delegate = self
// Register for remote notifications
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: { granted, error in
DispatchQueue.main.async {
if granted {
application.registerForRemoteNotifications()
}
}
}
)
return true
}
```
Your APNS token can change, so you need to handle the token refresh event and update the target with Appwrite Messaging.
Implement `didReceiveRegistrationToken`, which is called when the FCM token is updated.
```swift
func messaging(
_ messaging: FirebaseMessaging.Messaging,
didReceiveRegistrationToken fcmToken: String?
) {
guard let fcmToken = fcmToken else {
return
}
// Save the token to be used later
UserDefaults.standard.set(fcmToken , forKey: "fcmToken")
// Get the current Appwrite targetId from UserDefaults
let targetId = UserDefaults.standard.string(forKey: "targetId")
Task {
do {
_ = try await account.get()
} catch {
return // if not logged in, don't update the target
}
// if targetId is nil, create a new target
if targetId == nil {
let target = try? await account.createPushTarget(
targetId: ID.unique(),
identifier: fcmToken
)
UserDefaults.standard.set(target?.id , forKey: "targetId")
} else {
// if targetId exists for the Appwrite Account, update the target
_ = try? await account.updatePushTarget(
targetId: targetId!,
identifier: fcmToken
)
}
}
}
Since the token is saved in `UserDefaults`, you can access it from anywhere in your app.
With this saved `fcmToken`, you can create a push target with Appwrite when the user logs in.
Each push target is associated with an account, heres an example with a email password login.
The same logic applies to all types of login methods.
```swift
func login() async {
do {
let session = try await account.createEmailPasswordSession(
email: username,
password: password
)
guard let token = UserDefaults.standard.string(forKey: "fcmToken") else {
return
}
guard let target = try? await account.createPushTarget(
targetId: ID.unique(),
identifier: token
) else {
return
}
UserDefaults.standard.set(target.id, forKey: "targetId")
DispatchQueue.main.async {
self.response = String(describing: session.toMap())
}
} catch {
DispatchQueue.main.async {
self.response = error.localizedDescription
}
}
}
```
If you have disabled method swizzling, or you are building a SwiftUI app,
you'll need to explicitly map your APNs token to the FCM registration token.
Implement the `didRegisterForRemoteNotificationsWithDeviceToken` method to get the device token and save it to FCM.
```swift
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Messaging.messaging().apnsToken = deviceToken
}
```
{% /tabsitem %}
{% /tabs %}
{% /section %}
{% section #request-permissions step=3 title="Request permissions" %}
Your app must ask for permission to receive push notification from the user.
Appwrite provides an `OS` class to help simplify the process to handle permissions.
{% tabs %}
{% tabsitem #apple-apns title="Apple with APNs" %}
Before your app can receive push notifications, you need to request the user for permissions.
Appwrite provides a utility to help request permissions to display notificaitons.
```swift
OS.requestPermission(
application,
OSPermission.notifications,
onGranted: {
// Handle on permission granted
},
onDenied: {
// Handle on permission denied
}
)
```
{% /tabsitem %}
{% tabsitem #android-fcm title="FCM for Android" %}
First, add `POST_NOTIFICATIONS` to your `AndroidManifest.xml`.
```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="YOUR_PACKAGE">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<!-- ... rest of your manifest -->
```
Then, request permissions to display push notifications in your app.
Appwrite provides a utility to help request permissions.
```kotlin
OS.requestPermission(
this, // Context
Manifest.permission.POST_NOTIFICATIONS, // Permission requested
onGranted = {
println("Permission granted") // When permission is granted
},
onDenied = {
println("Permission denied") // When permission is denied
},
onShowRationale = {
println("Should show rationale") // Explain why this permission is needed.
}
)
```
{% /tabsitem %}
{% tabsitem #apple-fcm title="FCM for Apple" %}
Before your app can receive push notifications, you need to request the user for permissions.
Appwrite provides a utility to help request permissions to display notificaitons.
```swift
OS.requestPermission(
application,
OSPermission.notifications,
onGranted: {
// Handle on permission granted
},
onDenied: {
// Handle on permission denied
}
)
```
When an FCM registration token is generated, the library uploads the identifier and configuration data to Firebase.
If you wish to give your users the ability to explicitly opt out of sending data to Firebase,
you can disable automatic initialization and manually initialize the library when the user grants permission.
Disable auto-initialization by setting `FirebaseMessagingAutoInitEnabled` to `NO` in your `Info.plist`.
```text
FirebaseMessagingAutoInitEnabled = NO
```
Then, manually initialize the library when the user grants permission.
``` swift
Messaging.messaging().autoInitEnabled = true
```
{% /tabsitem %}
{% /tabs %}
{% /section %}
{% section #send-message step=4 title="Send message" %}
You can send messages in both the Appwrite Console and programmatically using the Appwrite Server SDK.
{% info title="APNs environment" %}
Appwrite sends push notifications to the APNs production environment by default.
This means, your development builds on XCode will not receive push notifications.
To test push notifications, click your root-level app in XCode > **Signing & Capabilities** > {% icon icon="plus" size="m" /%} Capabilities > uncheck **Automatically manage signing**.
Then manually select a **Provisioning profile** that is a **Distribution profile**.
{% /info %}
{% tabs %}
{% tabsitem #console title="Console" %}
To send a test message, navigate to **Messaging** > **Messages** > {% icon icon="plus" size="m" /%} **Create message** > **Push notification**.
{% only_dark %}
![Create email message](/images/docs/messaging/messages/dark/create-push-notification.png)
{% /only_dark %}
{% only_light %}
![Create email message](/images/docs/messaging/messages/create-push-notification.png)
{% /only_light %}
Add your message and in the targets step, select one of your test targets. Set the schedule to **Now** and click **Send**.
Verify that you can receive the message in your inbox. If not, check for logs in the Appwrite Console or in your provider's logs.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To send a message programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createPush(
'[MESSAGE_ID]', // messageId
'[TITLE]', // title
'[BODY]', // body
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
{}, // data (optional)
'[ACTION]', // action (optional)
'[ICON]', // icon (optional)
'[SOUND]', // sound (optional)
'[COLOR]', // color (optional)
'[TAG]', // tag (optional)
'[BADGE]', // badge (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createPush(
'[MESSAGE_ID]', // messageId
'[TITLE]', // title
'[BODY]', // body
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
{}, // data (optional)
'[ACTION]', // action (optional)
'[ICON]', // icon (optional)
'[SOUND]', // sound (optional)
'[COLOR]', // color (optional)
'[TAG]', // tag (optional)
'[BADGE]', // badge (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->createPush(
messageId: '[MESSAGE_ID]',
title: '[TITLE]',
body: '[BODY]',
topics: [], // optional
users: [], // optional
targets: [], // optional
data: [], // optional
action: '[ACTION]', // optional
icon: '[ICON]', // optional
sound: '[SOUND]', // optional
color: '[COLOR]', // optional
tag: '[TAG]', // optional
badge: '[BADGE]', // optional
status: 'draft', // optional
scheduledAt: '' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.create_push(
message_id = '[MESSAGE_ID]',
title = '[TITLE]',
body = '[BODY]',
topics = [], # optional
users = [], # optional
targets = [], # optional
data = {}, # optional
action = '[ACTION]',# optional
icon = '[ICON]', # optional
sound = '[SOUND]', # optional
color = '[COLOR]', # optional
tag = '[TAG]', # optional
badge = '[BADGE]', # optional
status = 'draft', # optional
scheduled_at = '' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.create_push(
message_id: '[MESSAGE_ID]',
title: '[TITLE]',
body: '[BODY]',
topics: [], # optional
users: [], # optional
targets: [], # optional
data: {}, # optional
action: '[ACTION]', # optional
icon: '[ICON]', # optional
sound: '[SOUND]', # optional
color: '[COLOR]', # optional
tag: '[TAG]', # optional
badge: '[BADGE]', # optional
status: 'draft', # optional
scheduled_at: '' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Message result = await messaging.CreatePush(
messageId: "[MESSAGE_ID]",
title: "[TITLE]",
body: "[BODY]"
topics: new List<string> {} // optional
users: new List<string> {} // optional
targets: new List<string> {} // optional
data: [object] // optional
action: "[ACTION]" // optional
icon: "[ICON]" // optional
sound: "[SOUND]" // optional
color: "[COLOR]" // optional
tag: "[TAG]" // optional
badge: "[BADGE]" // optional
status: "draft" // optional
scheduledAt: ""); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.createPush(
messageId: '[MESSAGE_ID]',
title: '[TITLE]',
body: '[BODY]',
topics: [], // optional
users: [], // optional
targets: [], // optional
data: {}, // optional
action: '[ACTION]', // optional
icon: '[ICON]', // optional
sound: '[SOUND]', // optional
color: '[COLOR]', // optional
tag: '[TAG]', // optional
badge: '[BADGE]', // optional
status: 'draft', // optional
scheduledAt: '', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client
import io.appwrite.services.Messaging
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
val messaging = Messaging(client)
val response = messaging.createPush(
messageId = "[MESSAGE_ID]",
title = "[TITLE]",
body = "[BODY]",
topics = listOf(), // optional
users = listOf(), // optional
targets = listOf(), // optional
data = mapOf( "a" to "b" ), // optional
action = "[ACTION]", // optional
icon = "[ICON]", // optional
sound = "[SOUND]", // optional
color = "[COLOR]", // optional
tag = "[TAG]", // optional
badge = "[BADGE]", // optional
status = "draft", // optional
scheduledAt = "" // optional
)
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createPush(
"[MESSAGE_ID]", // messageId
"[TITLE]", // title
"[BODY]", // body
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
mapOf( "a" to "b" ), // data (optional)
"[ACTION]", // action (optional)
"[ICON]", // icon (optional)
"[SOUND]", // sound (optional)
"[COLOR]", // color (optional)
"[TAG]", // tag (optional)
"[BADGE]", // badge (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let message = try await messaging.createPush(
messageId: "[MESSAGE_ID]",
title: "[TITLE]",
body: "[BODY]",
topics: [], // optional
users: [], // optional
targets: [], // optional
data: [:], // optional
action: "[ACTION]", // optional
icon: "[ICON]", // optional
sound: "[SOUND]", // optional
color: "[COLOR]", // optional
tag: "[TAG]", // optional
badge: "[BADGE]", // optional
status: "draft", // optional
scheduledAt: "" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,604 @@
---
layout: article
title: Sendgrid
description: Send emails to your Appwrite users using Sendgrid and Appwrite Messaging.
back: /docs/
---
Sendgrid lets you send customized email messages to your users.
These emails can be sent immediately or scheduled.
You can send emails for purposes like reminders, promotions, announcements, and even custom authentication flows.
{% section #add-provider step=1 title="Add provider" %}
To add Sendgrid as a provider, navigate to **Messaging** > **Providers** > {% icon icon="plus" size="m" /%} **Add provider** > **Email**.
{% only_dark %}
![Add a SMTP provider](/images/docs/messaging/providers/sendgrid/dark/add-sendgrid.png)
{% /only_dark %}
{% only_light %}
![Add a SMTP provider](/images/docs/messaging/providers/sendgrid/add-sendgrid.png)
{% /only_light %}
Give your provider a name > choose **Sendgrid** > click **Save and continue**.
The provider will be saved to your project, but not enabled until you complete its configuration.
{% /section %}
{% section #configure-provider step=2 title="Configure provider" %}
In the **Configure** step, you will need to provide details form your Sendgrid dashboard to connect your Appwrite project.
{% only_dark %}
![Configure SMTP provider](/images/docs/messaging/providers/sendgrid/dark/configure-sendgrid.png)
{% /only_dark %}
{% only_light %}
![Configure SMTP provider](/images/docs/messaging/providers/sendgrid/configure-sendgrid.png)
{% /only_light %}
You will need to provide the following information from your **Sendgrid dashboard**.
{% table %}
* Field name
*
---
* API key
* Head to Profile -> API Security -> Add new key.
---
* Domain
* Head to Sending -> Domains -> Add new domain.
Follow [Mailgun's instructions](https://help.mailgun.com/hc/en-us/articles/360026833053-Domain-Verification-Walkthrough) to verify the domain name.
---
* Sender email
* The provider sends emails from this sender email. The sender email needs to be an email under the configured domain.
---
* Sender name
* The sender name that appears in the emails sent from this provider.
---
* Reply-to email
* The reply-to email that appears in the emails sent from this provider. The reply-to email needs to be an email under the configured domain.
---
* Reply-to name
* The reply-to name that appears in the emails sent from this provider.
{% /table %}
After adding the following details, click **Save and continue** to enable the provider.
{% /section %}
{% section #test-provider step=3 title="Test provider" %}
Before sending your first message,
make sure you've configured [a topic](/docs/products/messaging/topics) and [a target](/docs/products/messaging/targets) to send messages to.
{% tabs %}
{% tabsitem #console title="Console" %}
To send a test message, navigate to **Messaging** > **Messages** > {% icon icon="plus" size="m" /%} **Create message** > **Email**.
{% only_dark %}
![Create email message](/images/docs/messaging/messages/dark/create-email-message.png)
{% /only_dark %}
{% only_light %}
![Create email message](/images/docs/messaging/messages/create-email-message.png)
{% /only_light %}
Add your message and in the targets step, select one of your test targets. Set the schedule to **Now** and click **Send**.
Verify that you can receive the message in your inbox. If not, check for logs in the Appwrite Console or in your provider's logs.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To send a message programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
const promise = messaging.createEmail('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>');
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
let promise = messaging.createEmail('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>');
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<PROJECT_ID>') // Your project ID
->setKey('<API_KEY>') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->createEmail('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>');
```
```python
from appwrite.client import Client
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
)
messaging = Messaging(client)
result = messaging.create_email('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>')
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
messaging = Messaging.new(client)
response = messaging.create_email(message_id: '<MESSAGE_ID>', subject: '<SUBJECT>', content: '<CONTENT>')
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
using Appwrite.Enums;
using Appwrite.Enums;
using Appwrite.Enums;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<PROJECT_ID>") // Your project ID
.SetKey("<API_KEY>"); // Your secret API key
var messaging = new Messaging(client);
Message result = await messaging.CreateEmail(
messageId: "<MESSAGE_ID>",
subject: "<SUBJECT>",
content: "<CONTENT>");
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
Future result = messaging.createEmail(
messageId:'<MESSAGE_ID>' ,
subject:'<SUBJECT>' ,
content:'<CONTENT>' ,
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Messaging
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
val messaging = Messaging(client)
val response = messaging.createEmail(
messageId = "<MESSAGE_ID>",
subject = "<SUBJECT>",
content = "<CONTENT>",
)
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createEmail(
"<MESSAGE_ID>",
"<SUBJECT>",
"<CONTENT>",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
let messaging = Messaging(client)
let message = try await messaging.createEmail(
messageId: "<MESSAGE_ID>",
subject: "<SUBJECT>",
content: "<CONTENT>"
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
You can follow the [Send email messages](/docs/products/messaging/send-email-messages) journey to send your first push notification and test your provider.
{% /section %}
{% section #manage-provider step=4 title="Manage provider" %}
{% tabs %}
{% tabsitem #console title="Console" %}
You can update or delete a provider in the Appwrite Console.
Navigate to **Messaging** > **Providers** > click your provider.
In the settings, you can update a provider's configuration or delete the provider.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To update or delete providers programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>') // Your secret API key
;
const promise = messaging.updateMailgunProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
'[API_KEY]', // apiKey (optional)
'[DOMAIN]', // domain (optional)
false, // isEuRegion (optional)
false, // enabled (optional)
'[FROM_NAME]', // fromName (optional)
'email@example.com', // fromEmail (optional)
'[REPLY_TO_NAME]', // replyToName (optional)
'[REPLY_TO_EMAIL]' // replyToEmail (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>') // Your secret API key
;
const promise = messaging.updateMailgunProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
'[API_KEY]', // apiKey (optional)
'[DOMAIN]', // domain (optional)
false, // isEuRegion (optional)
false, // enabled (optional)
'[FROM_NAME]', // fromName (optional)
'email@example.com', // fromEmail (optional)
'[REPLY_TO_NAME]', // replyToName (optional)
'[REPLY_TO_EMAIL]' // replyToEmail (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setKey('<YOUR_API_KEY>') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->updateMailgunProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
apiKey: '[API_KEY]', // optional
domain: '[DOMAIN]', // optional
isEuRegion: false, // optional
enabled: false, // optional
fromName: '[FROM_NAME]', // optional
fromEmail: 'email@example.com', // optional
replyToName: '[REPLY_TO_NAME]', // optional
replyToEmail: '[REPLY_TO_EMAIL]' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<YOUR_PROJECT_ID>') # Your project ID
.set_key('<YOUR_API_KEY>') # Your secret API key
)
messaging = Messaging(client)
result = messaging.update_mailgun_provider(
provider_id = '[PROVIDER_ID]',
name = '[NAME]', # optional
api_key = '[API_KEY]', # optional
domain = '[DOMAIN]', # optional
is_eu_region = False, # optional
enabled = False, # optional
from_name = '[FROM_NAME]', # optional
from_email = 'email@example.com', # optional
reply_to_name = '[REPLY_TO_NAME]', # optional
reply_to_email = '[REPLY_TO_EMAIL]' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<YOUR_PROJECT_ID>') # Your project ID
.set_key('<YOUR_API_KEY>') # Your secret API key
messaging = Messaging.new(client)
response = messaging.update_mailgun_provider(
provider_id: '[PROVIDER_ID]',
name: '[NAME]', # optional
api_key: '[API_KEY]', # optional
domain: '[DOMAIN]', # optional
is_eu_region: false, # optional
enabled: false, # optional
from_name: '[FROM_NAME]', # optional
from_email: 'email@example.com', # optional
reply_to_name: '[REPLY_TO_NAME]', # optional
reply_to_email: '[REPLY_TO_EMAIL]' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<YOUR_PROJECT_ID>") // Your project ID
.SetKey("<YOUR_API_KEY>"); // Your secret API key
var messaging = new Messaging(client);
Provider result = await messaging.UpdateMailgunProvider(
providerId: "[PROVIDER_ID]"
name: "[NAME]" // optional
apiKey: "[API_KEY]" // optional
domain: "[DOMAIN]" // optional
isEuRegion: false // optional
enabled: false // optional
fromName: "[FROM_NAME]" // optional
fromEmail: "email@example.com" // optional
replyToName: "[REPLY_TO_NAME]" // optional
replyToEmail: "[REPLY_TO_EMAIL]"); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>') // Your secret API key
;
Future result = messaging.updateMailgunProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
apiKey: '[API_KEY]', // optional
domain: '[DOMAIN]', // optional
isEuRegion: false, // optional
enabled: false, // optional
fromName: '[FROM_NAME]', // optional
fromEmail: 'email@example.com', // optional
replyToName: '[REPLY_TO_NAME]', // optional
replyToEmail: '[REPLY_TO_EMAIL]', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateMailgunProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
"[API_KEY]", // apiKey (optional)
"[DOMAIN]", // domain (optional)
false, // isEuRegion (optional)
false, // enabled (optional)
"[FROM_NAME]", // fromName (optional)
"email@example.com", // fromEmail (optional)
"[REPLY_TO_NAME]", // replyToName (optional)
"[REPLY_TO_EMAIL]" // replyToEmail (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateMailgunProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
"[API_KEY]", // apiKey (optional)
"[DOMAIN]", // domain (optional)
false, // isEuRegion (optional)
false, // enabled (optional)
"[FROM_NAME]", // fromName (optional)
"email@example.com", // fromEmail (optional)
"[REPLY_TO_NAME]", // replyToName (optional)
"[REPLY_TO_EMAIL]" // replyToEmail (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>") // Your secret API key
let messaging = Messaging(client)
let provider = try await messaging.updateMailgunProvider(
providerId: "[PROVIDER_ID]",
name: "[NAME]", // optional
apiKey: "[API_KEY]", // optional
domain: "[DOMAIN]", // optional
isEuRegion: xfalse, // optional
enabled: xfalse, // optional
fromName: "[FROM_NAME]", // optional
fromEmail: "email@example.com", // optional
replyToName: "[REPLY_TO_NAME]", // optional
replyToEmail: "[REPLY_TO_EMAIL]" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

View File

@@ -0,0 +1,611 @@
---
layout: article
title: SMTP
description: Send emails to your Appwrite users using SMTP and Appwrite Messaging.
back: /docs/
---
If you wish to use a third-party SMTP provider that Appwrite doesn't yet support or host your own SMTP
server, you can setup a custom SMTP provider for your project.
{% section #add-provider step=1 title="Add provider" %}
To add a custom SMTP server as a provider, navigate to **Messaging** > **Providers** > {% icon icon="plus" size="m" /%} **Add provider** > **Email**.
{% only_dark %}
![Add a SMTP provider](/images/docs/messaging/providers/smtp/dark/add-smtp.png)
{% /only_dark %}
{% only_light %}
![Add a SMTP provider](/images/docs/messaging/providers/smtp/add-smtp.png)
{% /only_light %}
Give your provider a name > choose **SMTP** > click **Save and continue**.
The provider will be saved to your project, but not enabled until you complete its configuration.
{% /section %}
{% section #configure-provider step=2 title="Configure provider" %}
In the **Configure** step, you will need to provide details form your SMTP dashboard to connect your Appwrite project.
You will need to provide the following information from your **SMTP dashboard**.
{% table %}
* Field name
*
---
* Host
* The server address of the SMTP provider.
---
* Port
* The port used for SMTP connections.
---
* Username
* Your SMTP provider account username.
---
* Password
* Your SMTP provider account password.
---
* Encryption
* The type of encryption used. One of SSL or TLS.
---
* Auto TLS
* Automatically uses TLS encryption if available.
---
* Mailer
* The SMTP server or provider.
---
* Sender email
* The provider sends emails from this sender email. The sender email needs to be an email under the configured domain.
---
* Sender name
* The sender name that appears in the emails sent from this provider.
---
* Reply-to email
* The reply-to email that appears in the emails sent from this provider. The reply-to email needs to be an email under the configured domain.
---
* Reply-to name
* The reply-to name that appears in the emails sent from this provider.
{% /table %}
After adding the following details, click **Save and continue** to enable the provider.
{% /section %}
{% section #test-provider step=3 title="Test provider" %}
Before sending your first message,
make sure you've configured [a topic](/docs/products/messaging/topics) and [a target](/docs/products/messaging/targets) to send messages to.
{% tabs %}
{% tabsitem #console title="Console" %}
To send a test message, navigate to **Messaging** > **Messages** > {% icon icon="plus" size="m" /%} **Create message** > **Email**.
{% only_dark %}
![Create email message](/images/docs/messaging/messages/dark/create-email-message.png)
{% /only_dark %}
{% only_light %}
![Create email message](/images/docs/messaging/messages/create-email-message.png)
{% /only_light %}
Add your message and in the targets step, select one of your test targets. Set the schedule to **Now** and click **Send**.
Verify that you can receive the message in your inbox. If not, check for logs in the Appwrite Console or in your provider's logs.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To send a message programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
const promise = messaging.createEmail('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>');
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
let promise = messaging.createEmail('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>');
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<PROJECT_ID>') // Your project ID
->setKey('<API_KEY>') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->createEmail('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>');
```
```python
from appwrite.client import Client
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
)
messaging = Messaging(client)
result = messaging.create_email('<MESSAGE_ID>', '<SUBJECT>', '<CONTENT>')
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
messaging = Messaging.new(client)
response = messaging.create_email(message_id: '<MESSAGE_ID>', subject: '<SUBJECT>', content: '<CONTENT>')
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
using Appwrite.Enums;
using Appwrite.Enums;
using Appwrite.Enums;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<PROJECT_ID>") // Your project ID
.SetKey("<API_KEY>"); // Your secret API key
var messaging = new Messaging(client);
Message result = await messaging.CreateEmail(
messageId: "<MESSAGE_ID>",
subject: "<SUBJECT>",
content: "<CONTENT>");
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
Future result = messaging.createEmail(
messageId:'<MESSAGE_ID>' ,
subject:'<SUBJECT>' ,
content:'<CONTENT>' ,
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Messaging
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
val messaging = Messaging(client)
val response = messaging.createEmail(
messageId = "<MESSAGE_ID>",
subject = "<SUBJECT>",
content = "<CONTENT>",
)
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createEmail(
"<MESSAGE_ID>",
"<SUBJECT>",
"<CONTENT>",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
let messaging = Messaging(client)
let message = try await messaging.createEmail(
messageId: "<MESSAGE_ID>",
subject: "<SUBJECT>",
content: "<CONTENT>"
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
You can follow the [Send email messages](/docs/products/messaging/send-push-notifications) journey to send your first push notification and test your provider.
{% /section %}
{% section #manage-provider step=4 title="Manage provider" %}
{% tabs %}
{% tabsitem #console title="Console" %}
You can update or delete a provider in the Appwrite Console.
Navigate to **Messaging** > **Providers** > click your provider.
In the settings, you can update a provider's configuration or delete the provider.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To update or delete providers programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
// update provider
messaging.updateSendgridProvider(
'<PROVIDER_ID>',
'<PROVIDER_NAME>',
'<API_KEY>',
'<DOMAIN>',
'<IS_EU_REGION?>',
'<SENDER_NAME>',
'<SENDER_EMAIL>',
'<REPLY_TO_NAME>',
'<REPLY_TO_EMAIL>',
'<ENABLED?>',
).then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
// delete provider
messaging.deleteProvider('<PROVIDER_ID>')
.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
// update provider
messaging.updateSendgridProvider(
'<PROVIDER_ID>',
'<PROVIDER_NAME>',
'<API_KEY>',
'<DOMAIN>',
'<IS_EU_REGION?>',
'<SENDER_NAME>',
'<SENDER_EMAIL>',
'<REPLY_TO_NAME>',
'<REPLY_TO_EMAIL>',
'<ENABLED?>',
).then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
// delete provider
messaging.deleteProvider('<PROVIDER_ID>')
.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<PROJECT_ID>') // Your project ID
->setKey('<API_KEY>') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->updateSendgridProvider(
'<PROVIDER_ID>',
'<PROVIDER_NAME>',
'<API_KEY>',
'<DOMAIN>',
'<IS_EU_REGION?>',
'<SENDER_NAME>',
'<SENDER_EMAIL>',
'<REPLY_TO_NAME>',
'<REPLY_TO_EMAIL>',
'<ENABLED?>',
);
```
```python
from appwrite.client import Client
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
)
messaging = Messaging(client)
result = messaging.update_sendgrid_provider(
'<PROVIDER_ID>',
'<PROVIDER_NAME>',
'<API_KEY>',
'<DOMAIN>',
'<IS_EU_REGION?>',
'<SENDER_NAME>',
'<SENDER_EMAIL>',
'<REPLY_TO_NAME>',
'<REPLY_TO_EMAIL>',
'<ENABLED?>',
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<PROJECT_ID>') # Your project ID
.set_key('<API_KEY>') # Your secret API key
messaging = Messaging.new(client)
response = messaging.update_sendgrid_provider(
provider_id: "<PROVIDER_ID>",
name: "<PROVIDER_NAME>",
api_key: "<API_KEY>",
domain: "<DOMAIN>",
isEuRegion: "<IS_EU_REGION?>",
from_name: "<SENDER_NAME>",
from_email: "<SENDER_EMAIL>",
reply_to_name: "<REPLY_TO_NAME>",
reply_to_email: "<REPLY_TO_EMAIL>",
enabled: "<ENABLED?>",
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
using Appwrite.Enums;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<PROJECT_ID>") // Your project ID
.SetKey("<API_KEY>"); // Your secret API key
var messaging = new Messaging(client);
Provider result = await messaging.UpdateSendgridProvider(
providerId: "<PROVIDER_ID>",
name: "<PROVIDER_NAME>",
apiKey: "<API_KEY>",
domain: "<DOMAIN>",
isEuRegion: "<IS_EU_REGION?>",
fromName: "<SENDER_NAME>",
fromEmail: "<SENDER_EMAIL>",
replyToName: "<REPLY_TO_NAME>",
replyToEmail: "<REPLY_TO_EMAIL>",
enabled: "<ENABLED?>",
);
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<PROJECT_ID>') // Your project ID
.setKey('<API_KEY>') // Your secret API key
;
Future result = messaging.updateSendgridProvider(
providerId: "<PROVIDER_ID>",
name: "<PROVIDER_NAME>",
apiKey: "<API_KEY>",
domain: "<DOMAIN>",
isEuRegion: "<IS_EU_REGION?>",
fromName: "<SENDER_NAME>",
fromEmail: "<SENDER_EMAIL>",
replyToName: "<REPLY_TO_NAME>",
replyToEmail: "<REPLY_TO_EMAIL>",
enabled: "<ENABLED?>",
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Messaging
val client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
val messaging = Messaging(client)
val response = messaging.updateSendgridProvider(
providerId = "<PROVIDER_ID>",
name = "<PROVIDER_NAME>",
apiKey = "<API_KEY>",
domain = "<DOMAIN>",
isEuRegion = "<IS_EU_REGION?>",
fromName = "<SENDER_NAME>",
fromEmail = "<SENDER_EMAIL>",
replyToName = "<REPLY_TO_NAME>",
replyToEmail = "<REPLY_TO_EMAIL>",
enabled = "<ENABLED?>",
)
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateSendgridProvider(
"<PROVIDER_ID>",
"<PROVIDER_NAME>",
"<API_KEY>",
"<DOMAIN>",
"<IS_EU_REGION?>",
"<SENDER_NAME>",
"<SENDER_EMAIL>",
"<REPLY_TO_NAME>",
"<REPLY_TO_EMAIL>",
"<ENABLED?>",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<PROJECT_ID>") // Your project ID
.setKey("<API_KEY>") // Your secret API key
let messaging = Messaging(client)
let provider = try await messaging.updateSendgridProvider(
providerId: "<PROVIDER_ID>",
name: "<PROVIDER_NAME>",
apiKey: "<API_KEY>",
domain: "<DOMAIN>",
isEuRegion: "<IS_EU_REGION?>",
fromName: "<SENDER_NAME>",
fromEmail: "<SENDER_EMAIL>",
replyToName: "<REPLY_TO_NAME>",
replyToEmail: "<REPLY_TO_EMAIL>",
enabled: "<ENABLED?>",
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

View File

@@ -0,0 +1,95 @@
---
layout: article
title: Targets
description: Manage avenues of communication by targetting user's device, email, or phone number in your notification and messages.
---
Targets are different ways a user can be reached.
For example, a user might have two emails, a phone number as well as a phone and a tablet with your app installed.
This means, the user has five different targets that you can deliver messages to.
{% only_dark %}
![Target overview](/images/docs/messaging/targets/dark/target-overview.png)
{% /only_dark %}
{% only_light %}
![Target overview](/images/docs/messaging/targets/target-overview.png)
{% /only_light %}
# Topics and targets {% #topics-and-targets %}
A user can have multiple targets, such as emails, phone numbers, and devices with your app installed.
These targets can subscribe to a topic, so when messages are published to a topic, all subscribed targets receive the message.
{% arrow_link href="/docs/products/messaging/topics" %}
Learn more about topics
{% /arrow_link %}
# Types of targets {% #types-of-targets %}
There are three types of targets you can use to reach your targets.
{% table %}
* Target Type
* Description
---
* **Email**
* Allows you to send emails to the user's email.
---
* **SMS**
* Allows you to send SMS messages to the user's phone.
---
* **Push notification**
* Allows you to send push notifications to the user's device.
{% /table %}
# Add a target {% #add-a-target %}
Before you can send messages, make sure you have the appropriate targets added for your user.
## Add email target {% #add-email-target%}
Verified emails for users that signed up with [email password](/docs/products/auth/email-password),
[magic URL](/docs/products/auth/magic-url), and [email OTP](/docs/products/auth/email-otp) login will already have a email target.
## Add SMS target {% #add-sms-target%}
Verified phone numbers for users that signed up with [Phone OTP](/docs/products/auth/phone-sms) login will already have a phone target.
## Add push notification target {% #add-push-notification-target%}
Push notifications require configuration on both the Appwrite platform and your client app's code.
{% tabs %}
{% tabsitem #fcm-ios title="iOS with FCM" %}
1. In your Firebase console, navigate to **Settings** > **General** > **Your apps** > add an **iOS** app.
1. Register and download your `google-services.json` config file.
1. Head to **Apple Developer Member Center** > **Program resources** > **Certificates, Identifiers & Profiles** > **Keys**. The key needs **Apple Push Notification Service** enabled.
1. Create a new key, note down the key ID and download your key.
1. In Firebase console, go to *Settings** > **Cloud Messaging** > **APNs authentication key** > click **Upload**. Upload your key here.{% only_dark %}![Enable Push Notification in XCode](/images/docs/messaging/targets/dark/xcode-enable-pn.png){% /only_dark %}{% only_light %}![Enable Push Notification in XCode](/images/docs/messaging/targets/xcode-enable-pn.png){% /only_light %}
1. Add push notification capability to your app by clicking your root-level app in XCode > **Signing & Capabilities** > {% icon icon="plus" size="m" /%} Capabilities > Search for **Push Notifications**.
1. If using SwiftUI, disable swizzling by setting `FirebaseAppDelegateProxyEnabled` to `NO` in your `Info.plist`.
{% /tabsitem %}
{% tabsitem #fcm-android title="Android with FCM" %}
1. In your Firebase console, navigate to **Settings** > **General** > **Your apps** > add an **Android** app.
1. Register and download your `google-services.json` config file.
1. Add `google-services.json` at the root of your project.
1. Add Google Services class path to your app-level Gradle dependencies block `"com.google.gms:google-services:4.4.0"`.
1. Add Google Services plugin to your app-level Gradle in the plugins block as `"com.google.gms.google-services"`.
1. Add notification handler service to `AndroidManifest.xml` inside the application tag, alongisde other activities.
```groovy
<service android:name="io.appwrite.NotificationHandler" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
```
{% /tabsitem %}
{% tabsitem #APNs-ios title="iOS with APNs" %}
1. Head to **Apple Developer Member Center** > **Program resources** > **Certificates, Identifiers & Profiles** > **Keys**. The key needs **Apple Push Notification Service** enabled.
1. Create a new key, note down the key ID and download your key.
1. Add push notification capability to your app by clicking your root-level app in XCode > **Signing & Capabilities** > {% icon icon="plus" size="m" /%} Capabilities > Search for **Push Notifications**.
{% only_dark %}
![Enable Push Notification in XCode](/images/docs/messaging/targets/dark/xcode-enable-pn.png)
{% /only_dark %}
{% only_light %}
![Enable Push Notification in XCode](/images/docs/messaging/targets/xcode-enable-pn.png)
{% /only_light %}
{% /tabsitem %}
{% /tabs %}

View File

@@ -0,0 +1,613 @@
---
layout: article
title: Telesign
description: Send SMS messages to your Appwrite users using Telesign and Appwrite Messaging.
back: /docs/
---
Telesign lets you send customized SMS messages to your users.
These SMS messages can be sent immediately or scheduled.
You can send SMS messages for purposes like reminders, promotions, announcements, and even custom authentication flows.
{% section #add-provider step=1 title="Add provider" %}
To add Telesign as a provider, navigate to **Messaging** > **Providers** > {% icon icon="plus" size="m" /%} **Add provider** > **SMS**.
{% only_dark %}
![Add a Telesign provider](/images/docs/messaging/providers/telesign/dark/provider.png)
{% /only_dark %}
{% only_light %}
![Add a Telesign provider](/images/docs/messaging/providers/telesign/provider.png)
{% /only_light %}
Give your provider a name > choose **Telesign** > click **Save and continue**.
The provider will be saved to your project, but not enabled until you complete its configuration.
{% /section %}
{% section #configure-provider step=2 title="Configure provider" %}
In the **Configure** step, you will need to provide details form your Telesign dashboard to connect your Appwrite project.
You will need to provide the following information from your **Telesign dashboard**.
{% table %}
* Field name
*
---
* Customer ID
* Head to **Telesign portal** > **Profile** > **Customer ID**.
---
* API Key
* Head to **Telesign portal** > **Profile** > **API Keys**.
---
* Sender number
* The number from which the SMS will be sent. You may need to first purchase a number from Telesign.
{% /table %}
After adding the following details, click **Save and continue** to enable the provider.
{% /section %}
{% section #test-provider step=3 title="Test provider" %}
Before sending your first message,
make sure you've configured [a topic](/docs/products/messaging/topics) and [a target](/docs/products/messaging/targets) to send messages to.
{% tabs %}
{% tabsitem #console title="Console" %}
To send a test message, navigate to **Messaging** > **Messages** > {% icon icon="plus" size="m" /%} **Create message** > **SMS**.
{% only_dark %}
![Create SMS message](/images/docs/messaging/messages/dark/create-sms-message.png)
{% /only_dark %}
{% only_light %}
![Create SMS message](/images/docs/messaging/messages/create-sms-message.png)
{% /only_light %}
Add your message and in the targets step, select one of your test targets. Set the schedule to **Now** and click **Send**.
Verify that you can receive the message in your inbox. If not, check for logs in the Appwrite Console or in your provider's logs.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To send a message programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createSMS(
'[MESSAGE_ID]', // messageId
'[CONTENT]', // content
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createSMS(
'[MESSAGE_ID]', // messageId
'[CONTENT]', // content
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->createSMS(
messageId: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], // optional
users: [], // optional
targets: [], // optional
status: 'draft', // optional
scheduledAt: '' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.create_sms(
message_id = '[MESSAGE_ID]',
content = '[CONTENT]',
topics = [], # optional
users = [], # optional
targets = [], # optional
status = 'draft', # optional
scheduled_at = '' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.create_sms(
message_id: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], # optional
users: [], # optional
targets: [], # optional
status: 'draft', # optional
scheduled_at: '' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Message result = await messaging.CreateSMS(
messageId: "[MESSAGE_ID]",
content: "[CONTENT]"
topics: new List<string> {} // optional
users: new List<string> {} // optional
targets: new List<string> {} // optional
status: "draft" // optional
scheduledAt: ""); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.createSMS(
messageId: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], // optional
users: [], // optional
targets: [], // optional
status: 'draft', // optional
scheduledAt: '', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createSMS(
"[MESSAGE_ID]", // messageId
"[CONTENT]", // content
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createSMS(
"[MESSAGE_ID]", // messageId
"[CONTENT]", // content
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let message = try await messaging.createSMS(
messageId: "[MESSAGE_ID]",
content: "[CONTENT]",
topics: [], // optional
users: [], // optional
targets: [], // optional
status: "draft", // optional
scheduledAt: "" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
You can follow the [Send SMS messages](/docs/products/messaging/send-sms-messages) journey to send your first push notification and test your provider.
{% /section %}
{% section #manage-provider step=4 title="Manage provider" %}
{% tabs %}
{% tabsitem #console title="Console" %}
You can update or delete a provider in the Appwrite Console.
Navigate to **Messaging** > **Providers** > click your provider.
In the settings, you can update a provider's configuration or delete the provider.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To update or delete providers programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateTelesignProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[USERNAME]', // username (optional)
'[PASSWORD]', // password (optional)
'[FROM]' // from (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateTelesignProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[USERNAME]', // username (optional)
'[PASSWORD]', // password (optional)
'[FROM]' // from (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->updateTelesignProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
username: '[USERNAME]', // optional
password: '[PASSWORD]', // optional
from: '[FROM]' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.update_telesign_provider(
provider_id = '[PROVIDER_ID]',
name = '[NAME]', # optional
enabled = False, # optional
username = '[USERNAME]', # optional
password = '[PASSWORD]', # optional
from = '[FROM]' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.update_telesign_provider(
provider_id: '[PROVIDER_ID]',
name: '[NAME]', # optional
enabled: false, # optional
username: '[USERNAME]', # optional
password: '[PASSWORD]', # optional
from: '[FROM]' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Provider result = await messaging.UpdateTelesignProvider(
providerId: "[PROVIDER_ID]"
name: "[NAME]" // optional
enabled: false // optional
username: "[USERNAME]" // optional
password: "[PASSWORD]" // optional
from: "[FROM]"); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.updateTelesignProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
username: '[USERNAME]', // optional
password: '[PASSWORD]', // optional
from: '[FROM]', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateTelesignProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[USERNAME]", // username (optional)
"[PASSWORD]", // password (optional)
"[FROM]" // from (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateTelesignProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[USERNAME]", // username (optional)
"[PASSWORD]", // password (optional)
"[FROM]" // from (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let provider = try await messaging.updateTelesignProvider(
providerId: "[PROVIDER_ID]",
name: "[NAME]", // optional
enabled: xfalse, // optional
username: "[USERNAME]", // optional
password: "[PASSWORD]", // optional
from: "[FROM]" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

View File

@@ -0,0 +1,613 @@
---
layout: article
title: TextMagic
description: Send SMS messages to your Appwrite users using TextMagic and Appwrite Messaging.
back: /docs/
---
TextMagic lets you send customized SMS messages to your users.
These SMS messages can be sent immediately or scheduled.
You can send SMS messages for purposes like reminders, promotions, announcements, and even custom authentication flows.
{% section #add-provider step=1 title="Add provider" %}
To add TextMagic as a provider, navigate to **Messaging** > **Providers** > {% icon icon="plus" size="m" /%} **Add provider** > **SMS**.
{% only_dark %}
![Add a Textmagic provider](/images/docs/messaging/providers/textmagic/dark/provider.png)
{% /only_dark %}
{% only_light %}
![Add a Textmagic provider](/images/docs/messaging/providers/textmagic/provider.png)
{% /only_light %}
Give your provider a name > choose **TextMagic** > click **Save and continue**.
The provider will be saved to your project, but not enabled until you complete its configuration.
{% /section %}
{% section #configure-provider step=2 title="Configure provider" %}
In the **Configure** step, you will need to provide details form your TextMagic dashboard to connect your Appwrite project.
You will need to provide the following information from your **TextMagic dashboard**.
{% table %}
* Field name
*
---
* API key
* Head to TextMagic dashboard > **Services** > **API** > **Add new API key**.
---
* Username
* Head to TextMagic dashboard > **My account** > **Username**.
---
* Sender number
* Head to TextMagic dashboard > **Services** > **Sender settings**.
{% /table %}
After adding the following details, click **Save and continue** to enable the provider.
{% /section %}
{% section #test-provider step=3 title="Test provider" %}
Before sending your first message,
make sure you've configured [a topic](/docs/products/messaging/topics) and [a target](/docs/products/messaging/targets) to send messages to.
{% tabs %}
{% tabsitem #console title="Console" %}
To send a test message, navigate to **Messaging** > **Messages** > {% icon icon="plus" size="m" /%} **Create message** > **SMS**.
{% only_dark %}
![Create email message](/images/docs/messaging/messages/dark/create-email-message.png)
{% /only_dark %}
{% only_light %}
![Create email message](/images/docs/messaging/messages/create-email-message.png)
{% /only_light %}
Add your message and in the targets step, select one of your test targets. Set the schedule to **Now** and click **Send**.
Verify that you can receive the message in your inbox. If not, check for logs in the Appwrite Console or in your provider's logs.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To send a message programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createSMS(
'[MESSAGE_ID]', // messageId
'[CONTENT]', // content
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createSMS(
'[MESSAGE_ID]', // messageId
'[CONTENT]', // content
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->createSMS(
messageId: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], // optional
users: [], // optional
targets: [], // optional
status: 'draft', // optional
scheduledAt: '' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.create_sms(
message_id = '[MESSAGE_ID]',
content = '[CONTENT]',
topics = [], # optional
users = [], # optional
targets = [], # optional
status = 'draft', # optional
scheduled_at = '' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.create_sms(
message_id: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], # optional
users: [], # optional
targets: [], # optional
status: 'draft', # optional
scheduled_at: '' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Message result = await messaging.CreateSMS(
messageId: "[MESSAGE_ID]",
content: "[CONTENT]"
topics: new List<string> {} // optional
users: new List<string> {} // optional
targets: new List<string> {} // optional
status: "draft" // optional
scheduledAt: ""); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.createSMS(
messageId: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], // optional
users: [], // optional
targets: [], // optional
status: 'draft', // optional
scheduledAt: '', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createSMS(
"[MESSAGE_ID]", // messageId
"[CONTENT]", // content
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createSMS(
"[MESSAGE_ID]", // messageId
"[CONTENT]", // content
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let message = try await messaging.createSMS(
messageId: "[MESSAGE_ID]",
content: "[CONTENT]",
topics: [], // optional
users: [], // optional
targets: [], // optional
status: "draft", // optional
scheduledAt: "" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
You can follow the [Send SMS messages](/docs/products/messaging/send-sms-messages) journey to send your first push notification and test your provider.
{% /section %}
{% section #manage-provider step=4 title="Manage provider" %}
{% tabs %}
{% tabsitem #console title="Console" %}
You can update or delete a provider in the Appwrite Console.
Navigate to **Messaging** > **Providers** > click your provider.
In the settings, you can update a provider's configuration or delete the provider.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To update or delete providers programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateTextmagicProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[USERNAME]', // username (optional)
'[API_KEY]', // apiKey (optional)
'[FROM]' // from (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateTextmagicProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[USERNAME]', // username (optional)
'[API_KEY]', // apiKey (optional)
'[FROM]' // from (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->updateTextmagicProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
username: '[USERNAME]', // optional
apiKey: '[API_KEY]', // optional
from: '[FROM]' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.update_textmagic_provider(
provider_id = '[PROVIDER_ID]',
name = '[NAME]', # optional
enabled = False, # optional
username = '[USERNAME]', # optional
api_key = '[API_KEY]', # optional
from = '[FROM]' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.update_textmagic_provider(
provider_id: '[PROVIDER_ID]',
name: '[NAME]', # optional
enabled: false, # optional
username: '[USERNAME]', # optional
api_key: '[API_KEY]', # optional
from: '[FROM]' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Provider result = await messaging.UpdateTextmagicProvider(
providerId: "[PROVIDER_ID]"
name: "[NAME]" // optional
enabled: false // optional
username: "[USERNAME]" // optional
apiKey: "[API_KEY]" // optional
from: "[FROM]"); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.updateTextmagicProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
username: '[USERNAME]', // optional
apiKey: '[API_KEY]', // optional
from: '[FROM]', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateTextmagicProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[USERNAME]", // username (optional)
"[API_KEY]", // apiKey (optional)
"[FROM]" // from (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateTextmagicProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[USERNAME]", // username (optional)
"[API_KEY]", // apiKey (optional)
"[FROM]" // from (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let provider = try await messaging.updateTextmagicProvider(
providerId: "[PROVIDER_ID]",
name: "[NAME]", // optional
enabled: xfalse, // optional
username: "[USERNAME]", // optional
apiKey: "[API_KEY]", // optional
from: "[FROM]" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

View File

@@ -0,0 +1,512 @@
---
layout: article
title: Topics
description: Allow groups of users to subscribe to a common topic and receive the same notifications.
---
In Appwrite Messaging, you can use topics to deliver messages to groups of users at once.
{% only_dark %}
![Add a target](/images/docs/messaging/topics/dark/topics.png)
{% /only_dark %}
{% only_light %}
![Add a target](/images/docs/messaging/topics/topics.png)
{% /only_light %}
# Topics and targets {% #topics-and-targets %}
A user can have multiple targets, such as emails, phone numbers, and devices with your app installed.
These targets can subscribe to a topic, so when messages are published to a topic, all subscribed targets receive the message.
{% arrow_link href="/docs/products/messaging/targets" %}
Learn more about targets
{% /arrow_link %}
# Organizing topics {% #organizing-topics %}
A topic should have semantic meaning.
For example, a topic can represent a group of customers that receing a common announcemennt or publishing public updates.
It's important to keep privacy in mind when using topics.
Prefer sending private information like chat messages by addressing individual targets attached to a user.
Topics are optimized for delivering the same message to large groups of users.
If you need to deliver messages to **all devices of the same user**, you can find a user's targets by calling `account.get()`.
# Create a topic {% #create-a-topic %}
You can create topics
{% tabs %}
{% tabsitem #console title="Console" %}
{% only_dark %}
![Add a topic](/images/docs/messaging/topics/dark/create-topics.png)
{% /only_dark %}
{% only_light %}
![Add a topic](/images/docs/messaging/topics/create-topics.png)
{% /only_light %}
Navigate to your Appwrite Console > **Messaging** > **Topics** > **Create topic**.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createTopic(
'[TOPIC_ID]', // topicId
'[NAME]' // name
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createTopic(
'[TOPIC_ID]', // topicId
'[NAME]' // name
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->createTopic(
topicId: '[TOPIC_ID]',
name: '[NAME]'
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.create_topic(
topic_id = '[TOPIC_ID]',
name = '[NAME]'
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.create_topic(
topic_id: '[TOPIC_ID]',
name: '[NAME]'
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Topic result = await messaging.CreateTopic(
topicId: "[TOPIC_ID]",
name: "[NAME]");
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.createTopic(
topicId: '[TOPIC_ID]',
name: '[NAME]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createTopic(
"[TOPIC_ID]", // topicId
"[NAME]" // name
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createTopic(
"[TOPIC_ID]", // topicId
"[NAME]" // name
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let topic = try await messaging.createTopic(
topicId: "[TOPIC_ID]",
name: "[NAME]"
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
# Subscribe targets to a topic {% #subscribe-targets-to-topics %}
{% tabs %}
{% tabsitem #console title="Console" %}
During development, you can subscribe targests to a topic for testing right in the Appwrite console.
{% only_dark %}
![Add a topic](/images/docs/messaging/topics/dark/add-subscriber.png)
{% /only_dark %}
{% only_light %}
![Add a topic](/images/docs/messaging/topics/add-subscriber.png)
{% /only_light %}
Navigate to your Appwrite Console > **Messaging** > **Topics** > click on your topic > **Subscribers** > **Create topic** > **Add subscriber**.
If you can't find the targets you'd like to add, see the [targets page](/docs/products/messaging/targets).
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setJWT('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...') // Your secret JSON Web Token
;
const promise = messaging.createSubscriber(
'[TOPIC_ID]', // topicId
'[SUBSCRIBER_ID]', // subscriberId
'[TARGET_ID]' // targetId
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setJWT('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...') // Your secret JSON Web Token
;
const promise = messaging.createSubscriber(
'[TOPIC_ID]', // topicId
'[SUBSCRIBER_ID]', // subscriberId
'[TARGET_ID]' // targetId
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setJWT('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...') // Your secret JSON Web Token
;
$messaging = new Messaging($client);
$result = $messaging->createSubscriber(
topicId: '[TOPIC_ID]',
subscriberId: '[SUBSCRIBER_ID]',
targetId: '[TARGET_ID]'
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_jwt('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...') # Your secret JSON Web Token
)
messaging = Messaging(client)
result = messaging.create_subscriber(
topic_id = '[TOPIC_ID]',
subscriber_id = '[SUBSCRIBER_ID]',
target_id = '[TARGET_ID]'
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_jwt('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...') # Your secret JSON Web Token
messaging = Messaging.new(client)
response = messaging.create_subscriber(
topic_id: '[TOPIC_ID]',
subscriber_id: '[SUBSCRIBER_ID]',
target_id: '[TARGET_ID]'
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..."); // Your secret JSON Web Token
var messaging = new Messaging(client);
Subscriber result = await messaging.CreateSubscriber(
topicId: "[TOPIC_ID]",
subscriberId: "[SUBSCRIBER_ID]",
targetId: "[TARGET_ID]");
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setJWT('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...') // Your secret JSON Web Token
;
Future result = messaging.createSubscriber(
topicId: '[TOPIC_ID]',
subscriberId: '[SUBSCRIBER_ID]',
targetId: '[TARGET_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..."); // Your secret JSON Web Token
Messaging messaging = new Messaging(client);
messaging.createSubscriber(
"[TOPIC_ID]", // topicId
"[SUBSCRIBER_ID]", // subscriberId
"[TARGET_ID]" // targetId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ..."); // Your secret JSON Web Token
Messaging messaging = new Messaging(client);
messaging.createSubscriber(
"[TOPIC_ID]", // topicId
"[SUBSCRIBER_ID]", // subscriberId
"[TARGET_ID]" // targetId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setJWT("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...") // Your secret JSON Web Token
let messaging = Messaging(client)
let subscriber = try await messaging.createSubscriber(
topicId: "[TOPIC_ID]",
subscriberId: "[SUBSCRIBER_ID]",
targetId: "[TARGET_ID]"
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}

View File

@@ -0,0 +1,612 @@
---
layout: article
title: Twilio
description: Send SMS messages to your Appwrite users using Twilio and Appwrite Messaging.
back: /docs/
---
Twilio lets you send customized SMS messages to your users.
These SMS messages can be sent immediately or scheduled.
You can send SMS messages for purposes like reminders, promotions, announcements, and even custom authentication flows.
{% section #add-provider step=1 title="Add provider" %}
To add Twilio as a provider, navigate to **Messaging** > **Providers** > {% icon icon="plus" size="m" /%} **Add provider** > **SMS**.
{% only_dark %}
![Add a Twilio provider](/images/docs/messaging/providers/twilio/dark/provider.png)
{% /only_dark %}
{% only_light %}
![Add a Twilio provider](/images/docs/messaging/providers/twilio/provider.png)
{% /only_light %}
Give your provider a name > choose **Twilio** > click **Save and continue**.
The provider will be saved to your project, but not enabled until you complete its configuration.
{% /section %}
{% section #configure-provider step=2 title="Configure provider" %}
In the **Configure** step, you will need to provide details form your Twilio dashboard to connect your Appwrite project.
You will need to provide the following information from your **Twilio dashboard**.
{% table %}
* Field name
*
---
* Account SID
* Head to Twilio console > **Account info** > **Account SID**.
---
* Auth token
* Head to Twilio console > **Account info** > **Auth Token**.
---
* Sender number
* You can access numbers by navigating to your Twilio console > **Develop** > **Phone Numbers** > **Manage** > **Active Numbers**.
{% /table %}
After adding the following details, click **Save and continue** to enable the provider.
{% /section %}
{% section #test-provider step=3 title="Test provider" %}
Before sending your first message,
make sure you've configured [a topic](/docs/products/messaging/topics) and [a target](/docs/products/messaging/targets) to send messages to.
{% tabs %}
{% tabsitem #console title="Console" %}
To send a test message, navigate to **Messaging** > **Messages** > {% icon icon="plus" size="m" /%} **Create message** > **SMS**.
{% only_dark %}
![Create an sms message](/images/docs/messaging/messages/dark/create-sms-message.png)
{% /only_dark %}
{% only_light %}
![Create an sms message](/images/docs/messaging/messages/create-sms-message.png)
{% /only_light %}
Add your message and in the targets step, select one of your test targets. Set the schedule to **Now** and click **Send**.
Verify that you can receive the message in your inbox. If not, check for logs in the Appwrite Console or in your provider's logs.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To send a message programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createSMS(
'[MESSAGE_ID]', // messageId
'[CONTENT]', // content
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createSMS(
'[MESSAGE_ID]', // messageId
'[CONTENT]', // content
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->createSMS(
messageId: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], // optional
users: [], // optional
targets: [], // optional
status: 'draft', // optional
scheduledAt: '' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.create_sms(
message_id = '[MESSAGE_ID]',
content = '[CONTENT]',
topics = [], # optional
users = [], # optional
targets = [], # optional
status = 'draft', # optional
scheduled_at = '' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.create_sms(
message_id: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], # optional
users: [], # optional
targets: [], # optional
status: 'draft', # optional
scheduled_at: '' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Message result = await messaging.CreateSMS(
messageId: "[MESSAGE_ID]",
content: "[CONTENT]"
topics: new List<string> {} // optional
users: new List<string> {} // optional
targets: new List<string> {} // optional
status: "draft" // optional
scheduledAt: ""); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.createSMS(
messageId: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], // optional
users: [], // optional
targets: [], // optional
status: 'draft', // optional
scheduledAt: '', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createSMS(
"[MESSAGE_ID]", // messageId
"[CONTENT]", // content
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createSMS(
"[MESSAGE_ID]", // messageId
"[CONTENT]", // content
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let message = try await messaging.createSMS(
messageId: "[MESSAGE_ID]",
content: "[CONTENT]",
topics: [], // optional
users: [], // optional
targets: [], // optional
status: "draft", // optional
scheduledAt: "" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}
{% section #manage-provider step=4 title="Manage provider" %}
{% tabs %}
{% tabsitem #console title="Console" %}
You can update or delete a provider in the Appwrite Console.
Navigate to **Messaging** > **Providers** > click your provider.
In the settings, you can update a provider's configuration or delete the provider.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To update or delete providers programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateTwilioProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[ACCOUNT_SID]', // accountSid (optional)
'[AUTH_TOKEN]', // authToken (optional)
'[FROM]' // from (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateTwilioProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[ACCOUNT_SID]', // accountSid (optional)
'[AUTH_TOKEN]', // authToken (optional)
'[FROM]' // from (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->updateTwilioProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
accountSid: '[ACCOUNT_SID]', // optional
authToken: '[AUTH_TOKEN]', // optional
from: '[FROM]' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.update_twilio_provider(
provider_id = '[PROVIDER_ID]',
name = '[NAME]', # optional
enabled = False, # optional
account_sid = '[ACCOUNT_SID]', # optional
auth_token = '[AUTH_TOKEN]', # optional
from = '[FROM]' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.update_twilio_provider(
provider_id: '[PROVIDER_ID]',
name: '[NAME]', # optional
enabled: false, # optional
account_sid: '[ACCOUNT_SID]', # optional
auth_token: '[AUTH_TOKEN]', # optional
from: '[FROM]' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Provider result = await messaging.UpdateTwilioProvider(
providerId: "[PROVIDER_ID]"
name: "[NAME]" // optional
enabled: false // optional
accountSid: "[ACCOUNT_SID]" // optional
authToken: "[AUTH_TOKEN]" // optional
from: "[FROM]"); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.updateTwilioProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
accountSid: '[ACCOUNT_SID]', // optional
authToken: '[AUTH_TOKEN]', // optional
from: '[FROM]', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateTwilioProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[ACCOUNT_SID]", // accountSid (optional)
"[AUTH_TOKEN]", // authToken (optional)
"[FROM]" // from (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateTwilioProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[ACCOUNT_SID]", // accountSid (optional)
"[AUTH_TOKEN]", // authToken (optional)
"[FROM]" // from (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let provider = try await messaging.updateTwilioProvider(
providerId: "[PROVIDER_ID]",
name: "[NAME]", // optional
enabled: xfalse, // optional
accountSid: "[ACCOUNT_SID]", // optional
authToken: "[AUTH_TOKEN]", // optional
from: "[FROM]" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

View File

@@ -0,0 +1,614 @@
---
layout: article
title: Vonage
description: Send SMS messages to your Appwrite users using Vonage and Appwrite Messaging.
back: /docs/
---
Vonage lets you send customized SMS messages to your users.
These SMS messages can be sent immediately or scheduled.
You can send SMS messages for purposes like reminders, promotions, announcements, and even custom authentication flows.
{% section #add-provider step=1 title="Add provider" %}
To add Vonage as a provider, navigate to **Messaging** > **Providers** > {% icon icon="plus" size="m" /%} **Add provider** > **SMS**.
{% only_dark %}
![Add a Vonage provider](/images/docs/messaging/providers/vonage/dark/provider.png)
{% /only_dark %}
{% only_light %}
![Add a Vonage provider](/images/docs/messaging/providers/vonage/provider.png)
{% /only_light %}
Give your provider a name > choose **Vonage** > click **Save and continue**.
The provider will be saved to your project, but not enabled until you complete its configuration.
{% /section %}
{% section #configure-provider step=2 title="Configure provider" %}
In the **Configure** step, you will need to provide details form your Vonage dashboard to connect your Appwrite project.
You will need to provide the following information from your **Vonage dashboard**.
{% table %}
* Field name
*
---
* API key
* Head to Vonage dashboard > **Build & manage** > **API settings** and copy the API key.
---
* API secret
* Head to Vonage dashboard > **Build & manage** > **API settings** and copy the API secret.
---
* Sender number
* You can access your numbers by navigating to Vonage dashboard > **Build & manage** > **Numbers** > **Your numbers**.
---
{% /table %}
After adding the following details, click **Save and continue** to enable the provider.
{% /section %}
{% section #test-provider step=3 title="Test provider" %}
Before sending your first message,
make sure you've configured [a topic](/docs/products/messaging/topics) and [a target](/docs/products/messaging/targets) to send messages to.
{% tabs %}
{% tabsitem #console title="Console" %}
To send a test message, navigate to **Messaging** > **Messages** > {% icon icon="plus" size="m" /%} **Create message** > **Email**.
{% only_dark %}
![Create email message](/images/docs/messaging/messages/dark/create-email-message.png)
{% /only_dark %}
{% only_light %}
![Create email message](/images/docs/messaging/messages/create-email-message.png)
{% /only_light %}
Add your message and in the targets step, select one of your test targets. Set the schedule to **Now** and click **Send**.
Verify that you can receive the message in your inbox. If not, check for logs in the Appwrite Console or in your provider's logs.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To send a message programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createSMS(
'[MESSAGE_ID]', // messageId
'[CONTENT]', // content
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.createSMS(
'[MESSAGE_ID]', // messageId
'[CONTENT]', // content
[], // topics (optional)
[], // users (optional)
[], // targets (optional)
'draft', // status (optional)
'' // scheduledAt (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->createSMS(
messageId: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], // optional
users: [], // optional
targets: [], // optional
status: 'draft', // optional
scheduledAt: '' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.create_sms(
message_id = '[MESSAGE_ID]',
content = '[CONTENT]',
topics = [], # optional
users = [], # optional
targets = [], # optional
status = 'draft', # optional
scheduled_at = '' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.create_sms(
message_id: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], # optional
users: [], # optional
targets: [], # optional
status: 'draft', # optional
scheduled_at: '' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Message result = await messaging.CreateSMS(
messageId: "[MESSAGE_ID]",
content: "[CONTENT]"
topics: new List<string> {} // optional
users: new List<string> {} // optional
targets: new List<string> {} // optional
status: "draft" // optional
scheduledAt: ""); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.createSMS(
messageId: '[MESSAGE_ID]',
content: '[CONTENT]',
topics: [], // optional
users: [], // optional
targets: [], // optional
status: 'draft', // optional
scheduledAt: '', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createSMS(
"[MESSAGE_ID]", // messageId
"[CONTENT]", // content
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.createSMS(
"[MESSAGE_ID]", // messageId
"[CONTENT]", // content
listOf(), // topics (optional)
listOf(), // users (optional)
listOf(), // targets (optional)
"draft", // status (optional)
"" // scheduledAt (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let message = try await messaging.createSMS(
messageId: "[MESSAGE_ID]",
content: "[CONTENT]",
topics: [], // optional
users: [], // optional
targets: [], // optional
status: "draft", // optional
scheduledAt: "" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
You can follow the [Send SMS messages](/docs/products/messaging/send-sms-messages) journey to send your first push notification and test your provider.
{% /section %}
{% section #manage-provider step=4 title="Manage provider" %}
{% tabs %}
{% tabsitem #console title="Console" %}
You can update or delete a provider in the Appwrite Console.
Navigate to **Messaging** > **Providers** > click your provider.
In the settings, you can update a provider's configuration or delete the provider.
{% /tabsitem %}
{% tabsitem #server-sdk title="Server SDK" %}
To update or delete providers programmatically, use an [Appwrite Server SDK](/docs/sdks#server).
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
const messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateVonageProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[API_KEY]', // apiKey (optional)
'[API_SECRET]', // apiSecret (optional)
'[FROM]' // from (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
let messaging = new sdk.Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
const promise = messaging.updateVonageProvider(
'[PROVIDER_ID]', // providerId
'[NAME]', // name (optional)
false, // enabled (optional)
'[API_KEY]', // apiKey (optional)
'[API_SECRET]', // apiSecret (optional)
'[FROM]' // from (optional)
);
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
```
```php
<?php
use Appwrite\Client;
use Appwrite\Services\Messaging;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('5df5acd0d48c2') // Your project ID
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
$messaging = new Messaging($client);
$result = $messaging->updateVonageProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
apiKey: '[API_KEY]', // optional
apiSecret: '[API_SECRET]', // optional
from: '[FROM]' // optional
);
```
```python
from appwrite.client import Client
from appwrite.services.messaging import Messaging
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
)
messaging = Messaging(client)
result = messaging.update_vonage_provider(
provider_id = '[PROVIDER_ID]',
name = '[NAME]', # optional
enabled = False, # optional
api_key = '[API_KEY]', # optional
api_secret = '[API_SECRET]', # optional
from = '[FROM]' # optional
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
messaging = Messaging.new(client)
response = messaging.update_vonage_provider(
provider_id: '[PROVIDER_ID]',
name: '[NAME]', # optional
enabled: false, # optional
api_key: '[API_KEY]', # optional
api_secret: '[API_SECRET]', # optional
from: '[FROM]' # optional
)
puts response.inspect
```
```csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("5df5acd0d48c2") // Your project ID
.SetKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
var messaging = new Messaging(client);
Provider result = await messaging.UpdateVonageProvider(
providerId: "[PROVIDER_ID]"
name: "[NAME]" // optional
enabled: false // optional
apiKey: "[API_KEY]" // optional
apiSecret: "[API_SECRET]" // optional
from: "[FROM]"); // optional
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
Messaging messaging = Messaging(client);
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('5df5acd0d48c2') // Your project ID
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
Future result = messaging.updateVonageProvider(
providerId: '[PROVIDER_ID]',
name: '[NAME]', // optional
enabled: false, // optional
apiKey: '[API_KEY]', // optional
apiSecret: '[API_SECRET]', // optional
from: '[FROM]', // optional
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error.response);
});
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateVonageProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[API_KEY]", // apiKey (optional)
"[API_SECRET]", // apiSecret (optional)
"[FROM]" // from (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Messaging;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2"); // Your secret API key
Messaging messaging = new Messaging(client);
messaging.updateVonageProvider(
"[PROVIDER_ID]", // providerId
"[NAME]", // name (optional)
false, // enabled (optional)
"[API_KEY]", // apiKey (optional)
"[API_SECRET]", // apiSecret (optional)
"[FROM]" // from (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
System.out.println(result);
})
);
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
.setKey("919c2d18fb5d4...a2ae413da83346ad2") // Your secret API key
let messaging = Messaging(client)
let provider = try await messaging.updateVonageProvider(
providerId: "[PROVIDER_ID]",
name: "[NAME]", // optional
enabled: xfalse, // optional
apiKey: "[API_KEY]", // optional
apiSecret: "[API_SECRET]", // optional
from: "[FROM]" // optional
)
```
{% /multicode %}
{% /tabsitem %}
{% /tabs %}
{% /section %}

View File

@@ -164,7 +164,6 @@ class MainActivity : AppCompatActivity() {
val storage = Storage(client)
GlobalScope.launch {
val result = storage.getFilePreview(
bucketId = "photos", // bucket ID
fileId = "sunset.png", // file ID
@@ -183,7 +182,6 @@ class MainActivity : AppCompatActivity() {
println(result); // Resource URL
}
}
}
```
{% /multicode %}

View File

@@ -24,7 +24,7 @@ To upload a file, add this to you web, Flutter, Apple, or Android app.
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
const storage = new Storage(client);
@@ -47,7 +47,7 @@ To upload a file, add this to you web, Flutter, Apple, or Android app.
void main() { // Init SDK
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
final storage = Storage(client);
@@ -66,7 +66,7 @@ To upload a file, add this to you web, Flutter, Apple, or Android app.
suspend fun main() {
val client = Client(applicationContext)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("[PROJECT_ID]") // Your project ID
.setProject("<PROJECT_ID>") // Your project ID
val storage = Storage(client)
@@ -84,7 +84,7 @@ To upload a file, add this to you web, Flutter, Apple, or Android app.
func main() async throws {
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[PROJECT_ID]")
.setProject("<PROJECT_ID>")
let storage = Storage(client)
@@ -218,7 +218,6 @@ class MainActivity : AppCompatActivity() {
val storage = Storage(client)
GlobalScope.launch {
val result = storage.getFileDownload(
bucketId = "[BUCKET_ID]",
fileId = "[FILE_ID]"
@@ -226,6 +225,5 @@ class MainActivity : AppCompatActivity() {
println(result); // Resource URL
}
}
}
```
{% /multicode %}

View File

@@ -20,7 +20,7 @@ You can also upload files programmatically using our SDKs:
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
const storage = new Storage(client);
@@ -43,7 +43,7 @@ You can also upload files programmatically using our SDKs:
void main() { // Init SDK
final client = Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT_ID]');
.setProject('<PROJECT_ID>');
final storage = Storage(client);
@@ -62,7 +62,7 @@ You can also upload files programmatically using our SDKs:
suspend fun main() {
val client = Client(applicationContext)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("[PROJECT_ID]") // Your project ID
.setProject("<PROJECT_ID>") // Your project ID
val storage = Storage(client)
@@ -80,7 +80,7 @@ You can also upload files programmatically using our SDKs:
func main() async throws {
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("[PROJECT_ID]")
.setProject("<PROJECT_ID>")
let storage = Storage(client)
@@ -370,7 +370,6 @@ class MainActivity : AppCompatActivity() {
val storage = Storage(client)
GlobalScope.launch {
val result = storage.getFile(
bucketId = "[BUCKET_ID]",
fileId = "[FILE_ID]"
@@ -378,7 +377,6 @@ class MainActivity : AppCompatActivity() {
println(result); // Resource URL
}
}
}
```
{% /multicode %}
@@ -475,7 +473,6 @@ class MainActivity : AppCompatActivity() {
val storage = Storage(client)
GlobalScope.launch {
val result = storage.getFileDownload(
bucketId = "[BUCKET_ID]",
fileId = "[FILE_ID]"
@@ -483,7 +480,6 @@ class MainActivity : AppCompatActivity() {
println(result); // Resource URL
}
}
}
```
{% /multicode %}
@@ -580,7 +576,6 @@ class MainActivity : AppCompatActivity() {
val storage = Storage(client)
GlobalScope.launch {
val result = storage.getFilePreview(
bucketId = "[BUCKET_ID]",
fileId = "[FILE_ID]"
@@ -588,7 +583,6 @@ class MainActivity : AppCompatActivity() {
println(result); // Resource URL
}
}
}
```
{% /multicode %}
@@ -686,7 +680,6 @@ class MainActivity : AppCompatActivity() {
val storage = Storage(client)
GlobalScope.launch {
val result = storage.getFileView(
bucketId = "[BUCKET_ID]",
fileId = "[FILE_ID]"
@@ -694,6 +687,5 @@ class MainActivity : AppCompatActivity() {
println(result); // Resource URL
}
}
}
```
{% /multicode %}

View File

@@ -112,7 +112,7 @@ object Appwrite {
email: String,
password: String,
): Session {
return account.createEmailSession(
return account.createEmailPasswordSession(
email,
password,
)

View File

@@ -82,7 +82,7 @@ export { ID } from 'appwrite';
```
{% /section %}
{% section #step-5 step=5 title="Create a login page" %}
First, add imports for the `FormsModule` from Angular to handle the login form..
First, add imports for the `FormsModule` from Angular to handle the login form.
```ts
import { FormsModule } from '@angular/forms';
@@ -144,7 +144,7 @@ export class AppComponent {
name: string = '';
async login(email: string, password: string) {
await account.createEmailSession(email, password);
await account.createEmailPasswordSession(email, password);
this.loggedInUser = await account.get();
}

View File

@@ -131,7 +131,7 @@ class Appwrite {
_ email: String,
_ password: String
) async throws -> Session {
try await account.createEmailSession(
try await account.createEmailPasswordSession(
email: email,
password: password
)

View File

@@ -214,7 +214,7 @@ class MyAppState extends State<MyApp> {
final TextEditingController nameController = TextEditingController();
Future<void> login(String email, String password) async {
await widget.account.createEmailSession(email: email, password: password);
await widget.account.createEmailPasswordSession(email: email, password: password);
final user = await widget.account.get();
setState(() {
loggedInUser = user;

View File

@@ -86,7 +86,7 @@ const LoginPage = () => {
const [name, setName] = useState("");
const login = async (email, password) => {
const session = await account.createEmailSession(email, password);
const session = await account.createEmailPasswordSession(email, password);
setLoggedInUser(await account.get());
};

View File

@@ -88,7 +88,7 @@ const password = ref('');
const name = ref('');
const login = async (email, password) => {
await account.createEmailSession(email, password);
await account.createEmailPasswordSession(email, password);
loggedInUser.value = await account.get();
};

View File

@@ -85,7 +85,7 @@ const App = () => {
const [name, setName] = useState('');
async function login(email, password) {
await account.createEmailSession(email, password);
await account.createEmailPasswordSession(email, password);
setLoggedInUser(await account.get());
}

View File

@@ -80,7 +80,7 @@ Replace the contents of `src/routes/+page.svelte` with the following code.
let loggedInUser = null;
async function login(email, password) {
await account.createEmailSession(email, password);
await account.createEmailPasswordSession(email, password);
loggedInUser = await account.get();
}

View File

@@ -107,7 +107,7 @@ const password = ref('');
const name = ref('');
const login = async (email, password) => {
await account.createEmailSession(email, password);
await account.createEmailPasswordSession(email, password);
loggedInUser.value = await account.get();
};

View File

@@ -17,6 +17,11 @@
label: 'Overview',
href: '/docs/references',
icon: 'icon-view-grid'
},
{
label: 'Quick start',
href: '/docs/references/quick-start',
icon: 'icon-play'
}
]
},

View File

@@ -1,5 +1,5 @@
The Account service allows you to authenticate and manage a user account. You can use the account service to update user information, retrieve the user sessions across different devices, and fetch the user security logs with his or her recent activity.
Register new user accounts with the [Create Account](/docs/references/cloud/client-web/account#create), [Create Magic URL session](/docs/references/cloud/client-web/account#createMagicURLSession), or [Create Phone session](/docs/references/cloud/client-web/account#createPhoneSession) endpoint. You can authenticate the user account by using multiple sign-in methods available. Once the user is authenticated, a new session object will be created to allow the user to access his or her private data and settings.
Register new user accounts with the [Create Account](/docs/references/cloud/client-web/account#create), [Create Magic URL session](/docs/references/cloud/client-web/account#createMagicURLToken), or [Create Phone session](/docs/references/cloud/client-web/account#createPhoneToken) endpoint. You can authenticate the user account by using multiple sign-in methods available. Once the user is authenticated, a new session object will be created to allow the user to access his or her private data and settings.
This service also exposes an endpoint to save and read the [user preferences](/docs/references/cloud/client-web/account#updatePrefs) as a key-value object. This feature is handy if you want to allow extra customization in your app. Common usage for this feature may include saving the user's preferred locale, timezone, or custom app theme.

View File

@@ -1 +1,5 @@
todo
Appwrite Messaging helps you communicate with your users through push notifications, emails, and SMS text messages.
Sending personalized communication for marketing, updates, and realtime alerts can increase user engagement and retention.
You can also use Appwrite Messaging to implement security checks and custom authentication flows.
You can find guides and examples on using the Messaging API in the [Appwrite Messaging product pages](/docs/products/messaging).

View File

@@ -0,0 +1,393 @@
---
layout: article
title: Quick start
description: Configure the Appwrite SDKs and take the necessary steps to start using Appwrite.
---
Follow these steps before you begin using the Appwrite SDKs or accessing Appwrite through the REST and GraphQL API.
{% section #select-the-right-API step=1 title="Select the right API" %}
Appwrite has two types of APIs for different use cases, select one or both depending on your use case.
If you're creating a **web, mobile, or native application** used by end-users that will register and create accounts,
install a [Client SDK](/docs/sdks#client) and follow steps for Client APIs.
If you're create a server application, like a **backend, admin app, or a CLI tool**,
install a [Server SDK](/docs/sdks#server) and follow steps for Server APIs.
If you're creating a **Server-side Rendered (SSR)** web app,
install a [Server SDK](/docs/sdks#server) and follow steps for SSR.
{% /section %}
{% section #configure-project step=2 title="Configure project" %}
Head to the [Appwrite Console](https://cloud.appwrite.io/console).
If this is your first time using Appwrite, create an account and create your first project.
{% only_dark %}
![Create project screen](/images/docs/quick-starts/dark/create-project.png)
{% /only_dark %}
{% only_light %}
![Create project screen](/images/docs/quick-starts/create-project.png)
{% /only_light %}
Then, configure your project depending on use case.
You can follow all three flows to enable all three use cases.
{% tabs %}
{% tabsitem #client title="Client" %}
Under **Add a platform**, add a platform for **each** web, mobile, and native app you plan to create.
This means, a different platform for each web app hosted under a different domain,
and a different platform for each mobile or native app that use a different package ID.
{% only_dark %}
![Add a platform](/images/docs/quick-starts/dark/add-platform.png)
{% /only_dark %}
{% only_light %}
![Add a platform](/images/docs/quick-starts/add-platform.png)
{% /only_light %}
You can skip optional steps.
{% /tabsitem %}
{% tabsitem #server title="Server" %}
Under **Integrate with your server**, add an **API Key**.
{% only_dark %}
![Create project screen](/images/docs/quick-starts/dark/integrate-server.png)
{% /only_dark %}
{% only_light %}
![Create project screen](/images/docs/quick-starts/integrate-server.png)
{% /only_light %}
Enable the scopes for the Appwrite products you plan to use for your app.
It's a good idea to only grant scopes that you need, and edit the API keys as your needs change for security.
{% /tabsitem %}
{% tabsitem #ssr title="SSR" %}
Under **Integrate with your server**, add an **API Key** with the following scopes.
{% only_dark %}
![Create project screen](/images/docs/quick-starts/dark/integrate-server.png)
{% /only_dark %}
{% only_light %}
![Create project screen](/images/docs/quick-starts/integrate-server.png)
{% /only_light %}
| Category {% width=120 %} | Required scopes | Purpose |
|-----------|-----------------------|---------|
| Sessions | `sessions.write` | Allows API key to create, update, and delete sessions. |
{% /tabsitem %}
{% /tabs %}
{% /section %}
{% section #initialize-sdks step=3 title="Initialize SDKs" %}
When using the Appwrite APIs, you need to pass information like endpoint, project ID, credentials
and other metadata for Appwrite to properly parse your request.
{% tabs %}
{% tabsitem #client title="Client" %}
Client apps need to be configured with endpoint and project ID,
so the Appwrite SDK knows which endpoint and project to connect to.
{% multicode %}
```js
import { Client } from "appwrite";
const client = new Client();
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
;
```
```dart
import 'package:appwrite/appwrite.dart';
Client client = Client();
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
;
```
```kotlin
import io.appwrite.Client
val client = Client(context)
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
```
{% /multicode %}
{% /tabsitem %}
{% tabsitem #server title="Server" %}
Server apps need to be configured with endpoint, project ID, and an API key
so the Appwrite SDK knows which endpoint and project to connect to, as well as have credentials to perform admin actions.
{% multicode %}
```js
const sdk = require('node-appwrite');
// Init SDK
const client = new sdk.Client();
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setJWT('<YOUR_API_KEY>') // Your secret JSON Web Token
;
```
```deno
import * as sdk from "https://deno.land/x/appwrite/mod.ts";
// Init SDK
let client = new sdk.Client();
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setJWT('<YOUR_API_KEY>') // Your secret JSON Web Token
;
```
```php
<?php
use Appwrite\Client;
$client = new Client();
$client
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setJWT('<YOUR_API_KEY>') // Your secret JSON Web Token
;
```
```python
from appwrite.client import Client
client = Client()
(client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<YOUR_PROJECT_ID>') # Your project ID
.set_jwt('<YOUR_API_KEY>') # Your secret JSON Web Token
)
```
```ruby
require 'appwrite'
include Appwrite
client = Client.new
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('<YOUR_PROJECT_ID>') # Your project ID
.set_jwt('<YOUR_API_KEY>') # Your secret JSON Web Token
```
```csharp
using Appwrite;
using Appwrite.Services;
var client = new Client()
.SetEndPoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.SetProject("<YOUR_PROJECT_ID>") // Your project ID
.SetJWT("<YOUR_API_KEY>"); // Your secret JSON Web Token
```
```dart
import 'package:dart_appwrite/dart_appwrite.dart';
void main() { // Init SDK
Client client = Client();
client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setJWT('<YOUR_API_KEY>') // Your secret JSON Web Token
;
}
```
```kotlin
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setJWT("<YOUR_API_KEY>"); // Your secret JSON Web Token
```
```java
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
Client client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setJWT("<YOUR_API_KEY>"); // Your secret JSON Web Token
```
```swift
import Appwrite
let client = Client()
.setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setJWT("<YOUR_API_KEY>") // Your secret JSON Web Token
```
{% /multicode %}
{% /tabsitem %}
{% tabsitem #ssr title="SSR" %}
Appwrite uses Server SDKs for SSR apps. The initialization is different
## Admin client {% #admin-client %}
{% info title="Admin clients" %}
Admin clients should only be used if you need to perform admin actions that bypass permissions
or [unauthenticated requests that bypass rate limits](/docs/products/auth/server-side-rendering#rate-limits).
{% /info %}
To initialize the admin client, we'll need to first [generated an API key](/docs/advanced/platform/api-keys#create-api-key).
The API key should have the following scope in order to perform authentication:
| Category {% width=120 %} | Required scopes | Purpose |
|-----------|---------------------|---------|
| Sessions | `sessions.write` | Allows API key to create, update, and delete sessions. |
{% multicode %}
```js
import { Client } from "node-appwrite"; // Using the server SDK
const adminClient = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>') // Your project ID
.setKey('<YOUR_API_KEY>'); // Your secret API key
```
```php
use Appwrite\Client;
use Appwrite\Services\Account;
$adminClient = (new Client())
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>') // Your project ID
->setKey('<YOUR_API_KEY>'); // Your secret API key
```
{% /multicode %}
It is important to use an API key, as this will allow your server requests to bypass [rate limits](/docs/advanced/platform/rate-limits). If you don't use an API key, your server will be rate limited as if it were a client from a single IP address.
## Session client {% #session-client %}
The session client will be used to make requests to Appwrite on behalf of the end-user.
It will be initialized with the session, usually stored within a cookie.
You should create a new client for each request and **never** share the client between requests.
{% multicode %}
```js
const sessionClient = new Client()
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
.setProject('<YOUR_PROJECT_ID>'); // Your project ID
const session = req.cookies.session; // Get the session cookie from the request
if (session) {
sessionClient.setSession(session);
}
```
```php
$sessionClient = (new Client())
->setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
->setProject('<YOUR_PROJECT_ID>'); // Your project ID
$session = $_COOKIE['session']; // Get the session cookie from the request
if ($session) {
$sessionClient->setSession($session);
}
```
{% /multicode %}
{% /tabsitem %}
You will use the initialized client in all requests you make to Appwrite.
{% /tabs %}
If you're using Appwrite without an SDK, follow the guides for the [REST API](/docs/apis/rest) or [GraphQL API](/docs/apis/graphql).
{% /section %}
{% section #examples step=4 title="Examples" %}
If you prefer to explore examples, follow one of the following quick starts.
## Client apps {% #client-app %}
Examples when building with Client APIs
{% cards %}
{% cards_item href="/docs/quick-starts/web" title="Web" icon="icon-nextjs" %}
Just plain JavaScript and TypeScript.
{% /cards_item %}
{% cards_item href="/docs/quick-starts/nextjs" title="Next.js" icon="icon-nextjs" %}
Get started with Appwrite and Next.js
{% /cards_item %}
{% cards_item href="/docs/quick-starts/react" title="React" icon="icon-react" %}
Get started with Appwrite and React
{% /cards_item %}
{% cards_item href="/docs/quick-starts/vue" title="Vue.js" icon="aw-icon-vue" %}
Get started with Appwrite and Vue.js
{% /cards_item %}
{% cards_item href="/docs/quick-starts/nuxt" title="Nuxt" icon="aw-icon-nuxt" %}
Get started with Appwrite and Nuxt
{% /cards_item %}
{% cards_item href="/docs/quick-starts/sveltekit" title="SvelteKit" icon="icon-svelte" %}
Get started with Appwrite and SvelteKit
{% /cards_item %}
{% cards_item href="/docs/quick-starts/angular" title="Angular" icon="icon-angular" %}
Get started with Appwrite and Angular
{% /cards_item %}
{% cards_item href="/docs/quick-starts/flutter" title="Flutter" icon="icon-flutter" %}
Get started with Appwrite and Flutter
{% /cards_item %}
{% cards_item href="/docs/quick-starts/apple" title="Apple" icon="icon-apple" %}
Get started with Appwrite and Apple
{% /cards_item %}
{% cards_item href="/docs/quick-starts/android" title="Android" icon="icon-android" %}
Get started with Appwrite and Android
{% /cards_item %}
{% /cards %}
## Server apps {% #server-app %}
Examples when building with Server APIs
{% cards %}
{% cards_item href="/docs/quick-starts/node" title="Node.js" icon="icon-node_js" %}
Get started with Appwrite and Node.js
{% /cards_item %}
{% cards_item href="/docs/quick-starts/python" title="Python" icon="icon-python" %}
Get started with Appwrite and Python
{% /cards_item %}
{% cards_item href="/docs/quick-starts/dotnet" title=".NET" icon="icon-dotnet" %}
Get started with Appwrite and .NET
{% /cards_item %}
{% cards_item href="/docs/quick-starts/dart" title="Dart" icon="icon-dart" %}
Get started with Appwrite and Dart
{% /cards_item %}
{% cards_item href="/docs/quick-starts/ruby" title="Ruby" icon="icon-ruby" %}
Get started with Appwrite and Ruby
{% /cards_item %}
{% cards_item href="/docs/quick-starts/deno" title="Deno" icon="icon-deno" %}
Get started with Appwrite and Deno
{% /cards_item %}
{% cards_item href="/docs/quick-starts/php" title="PHP" icon="icon-php" %}
Get started with Appwrite and PHP
{% /cards_item %}
{% cards_item href="/docs/quick-starts/kotlin" title="Kotlin" icon="icon-kotlin" %}
Get started with Appwrite and Kotlin
{% /cards_item %}
{% cards_item href="/docs/quick-starts/swift" title="Swift" icon="icon-swift" %}
Get started with Appwrite and Swift
{% /cards_item %}
{% /cards %}
{% /section %}

View File

@@ -17,12 +17,18 @@
angular: 'icon-angular',
svelte: 'icon-svelte',
sveltekit: 'icon-svelte',
'sveltekit ssr': 'icon-svelte',
android: 'icon-android',
apple: 'icon-apple',
flutter: 'icon-flutter',
nuxt: 'icon-nuxt',
'nuxt ssr': 'icon-nuxt',
stripe: 'icon-stripe',
refine: 'aw-icon-refine'
refine: 'aw-icon-refine',
'next.js': 'icon-nextjs',
'next.js ssr': 'icon-nextjs',
astro: 'icon-astro',
'astro ssr': 'icon-astro'
};
const getIcon = (tutorial: MappedTutorial) => {

View File

@@ -34,7 +34,7 @@ class AccountService(client: Client) {
suspend fun login(email: String, password: String): User<Map<String, Any>>? {
return try {
account.createEmailSession(email, password)
account.createEmailPasswordSession(email, password)
getLoggedIn()
} catch (e: AppwriteException) {
null

View File

@@ -0,0 +1,10 @@
<script lang="ts">
import { globToTutorial } from '$lib/utils/tutorials.js';
import { setContext } from 'svelte';
export let data;
const tutorials = globToTutorial(data);
setContext('tutorials', tutorials);
</script>
<slot />

View File

@@ -0,0 +1,5 @@
import { redirect } from '@sveltejs/kit';
export async function load() {
throw redirect(303, '/docs/tutorials/astro-ssr-auth/step-1');
}

View File

@@ -0,0 +1,19 @@
---
layout: tutorial
title: Server-side authentication with Astro
description: Add SSR authentication to your Astro app with Appwrite
step: 1
difficulty: beginner
readtime: 20
framework: Astro SSR
category: Auth
---
Appwrite takes away the stress of building and maintaining a backend. Appwrite helps implement authentication, databases, file storage, and respond to real-time events with **secure** APIs out of the box.
If you're a Astro developer, the examples in this guide show you how Appwrite can help you add authentication to Astro apps faster.
# Before you start {% #before-you-start %}
Even if you've never tried Appwrite, you will get an idea of what it'll feel like to build with Astro and Appwrite.
Clone the [demos-for-astro](https://github.com/appwrite/demos-for-astro) examples and follow along with the source code.

View File

@@ -0,0 +1,41 @@
---
layout: tutorial
title: Create project
description: Add authentication to a Astro project using Appwrite.
step: 2
---
Create an [Astro project](https://docs.astro.build/en/install/auto/#1-run-the-setup-wizard) using:
```sh
npm create astro@latest
```
The command prompt will be something similar to this.
```sh
Where should we create your new project? ./my-astro-project
How would you like to start your new project? Empty
Do you plan to write TypeScript? No
Install dependencies? Yes
Initialize a new git repository? Yes
```
After the prompt is finished, you can head over to the newly create project.
```sh
cd my-astro-project
```
# Install Appwrite {% #install-appwrite %}
Appwrite provides a Node SDK that can be used in your Astro apps. You can use Appwrite by installing the Node SDK as an NPM package. The Node SDK is intended for server-side use. If you want to use Appwrite in a client-side application, you should use the Web SDK instead.
```sh
npm install node-appwrite
```

View File

@@ -0,0 +1,112 @@
---
layout: tutorial
title: Initialize SDK
description: Add authentication to a Astro project using Appwrite.
step: 3
---
Before you can use Appwrite, you need to create the Appwrite `Client` and set the project ID and endpoint.
The client is then used to create services like `Databases` and `Account`, so they all point to the same Appwrite project.
Create a function to build services you need in a file like `src/server/appwrite.js` and **exporting the instances**.
As part of the function, set the current user's session if they are logged in. This is done by accessing the session cookie from the request and calling the `setSession(session)` with the cookie value.
{% info title="Appwrite client security" %}
Notice that `createAppwriteClient` returns **a new instance** of the Appwrite Client.
When using Appwrite in server-integrations, it's important to **never share a `Client` instance** between two requests.
Doing so could create security vulnerabilities.
{% /info %}
```js
// src/server/appwrite.js
import { Client, Account } from "node-appwrite";
// The name of your cookie that will store the session
export const SESSION_COOKIE = "my-custom-session";
// Admin client, used to create new accounts
export function createAdminClient() {
const client = new Client()
.setEndpoint(import.meta.env.PUBLIC_APPWRITE_ENDPOINT)
.setProject(import.meta.env.PUBLIC_APPWRITE_PROJECT_ID)
.setKey(import.meta.env.APPWRITE_KEY); // Set the API key here!
// Return the services you need
return {
get account() {
return new Account(client);
},
};
}
// Session client, used to make requests on behalf of the logged in user
export function createSessionClient(request) {
const client = new Client()
.setEndpoint(import.meta.env.PUBLIC_APPWRITE_ENDPOINT)
.setProject(import.meta.env.PUBLIC_APPWRITE_PROJECT_ID);
// Get the session cookie from the request and set the session
const cookies = parseCookies(request.headers.get("cookie") ?? "");
const session = cookies.get(SESSION_COOKIE);
if (session) {
client.setSession(session);
}
// Return the services you need
return {
get account() {
return new Account(client);
},
};
}
// Helper function to parse cookies
function parseCookies(cookies) {
const map = new Map();
for (const cookie of cookies.split(";")) {
const [name, value] = cookie.split("=");
map.set(name.trim(), value ?? null);
}
return map;
}
```
`import.meta.env.APPWRITE_KEY`, `import.meta.env.PUBLIC_APPWRITE_ENDPOINT` and `import.meta.env.PUBLIC_APPWRITE_PROJECT_ID` are environment variables that are exported in your project's [.env file](https://kit.Astro.dev/docs/modules#$env-dynamic-public).
You can get the values for these variables from the Appwrite console.
The `PUBLIC_APPWRITE_ENDPOINT` is the endpoint of your Appwrite project, and the `PUBLIC_APPWRITE_PROJECT` is the ID of the project you want to use.
You can get the values for these variables from the Appwrite console.
{% only_dark %}
![Create project screen](/images/docs/quick-starts/dark/create-project.png)
{% /only_dark %}
{% only_light %}
![Create project screen](/images/docs/quick-starts/create-project.png)
{% /only_light %}
The `APPWRITE_KEY` is an Appwrite API key with the necessary permissions to read and write accounts and sessions.
For this tutorial you'll need an API key with the following scopes:
| Category {% width=120 %} | Required scopes | Purpose |
| ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ |
| Sessions | `sessions.write` | Allows API key to create, update, and delete sessions. |
{% only_dark %}
![Server integrations](/images/docs/quick-starts/dark/integrate-server.png)
{% /only_dark %}
{% only_light %}
![Server integrations](/images/docs/quick-starts/integrate-server.png)
{% /only_light %}
For example, your `.env` might look something similar to this.
```text
APPWRITE_KEY=<YOUR_API_KEY>
PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
PUBLIC_APPWRITE_PROJECT=<YOUR_PROJECT_ID>
```

View File

@@ -0,0 +1,65 @@
---
layout: tutorial
title: Add a server hook
description: Add authentication to a Astro project using Appwrite.
step: 4
---
Astro middleware are functions that run on the server before a page is displayed to the user. Astro locals are a way to store data that is specific to the current request. We can use these features to store the user's account data, so that it is available to all pages.
Create a new file in the `src/server` directory called `middleware.js`:
```js
// src/server/middleware.js
import { defineMiddleware } from "astro:middleware";
import { createSessionClient } from "./server/appwrite";
export const onRequest = defineMiddleware(async ({ request, locals }, next) => {
const { account } = createSessionClient(request);
try {
locals.user = await account.get();
} catch {}
return next();
});
```
To ensure the `locals` object is typed correctly, we can add a type definition for it in the `env.d.ts` file:
```ts
// <reference types="astro/client" />
declare namespace App {
interface Locals {
user?:
| import("node-appwrite").Models.User<
import("node-appwrite").Models.Preferences<{}>
>
}
}
interface ImportMetaEnv {
readonly PUBLIC_APPWRITE_ENDPOINT: string;
readonly PUBLIC_APPWRITE_PROJECT_ID: string;
readonly APPWRITE_KEY: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
```
Now, use the `locals` object in the home page to redirect based on the user's login status. Create a new file in the `src/pages` directory called `index.astro`:
```js
---
const { user } = Astro.locals;
if (user) {
return Astro.redirect("/account");
}
return Astro.redirect("/signin");
---
```
When a user visits the home page, they will be redirected to the sign in page if they are not logged in, or to the account page if they are logged in.

View File

@@ -0,0 +1,58 @@
---
layout: tutorial
title: Create sign in page
description: Add authentication to a Astro project using Appwrite.
step: 5
---
We can now implement our sign in page. Create a `signin.astro` file in the `src/pages` directory:
```js
---
const { user } = Astro.locals;
if (user) {
return Astro.redirect("/account");
}
---
<form method="POST">
<input id="email" name="email" placeholder="Email" type="email" />
<input id="password" name="email" placeholder="Password" type="password" />
<button class="button is-full-width" type="submit"> Sign in</button>
</form>
```
This is an HTML form with an email and password input. When the form is submitted, we want to send the email and password to Appwrite to authenticate the user. To use Astro form actions, add an `if (Astro.request.method === "POST")` statement to the server-side javascript.
```js
---
import { SESSION_COOKIE, createAdminClient } from "../server/appwrite";
// ... existing javascript
if (Astro.request.method === "POST") {
// Extract the form data
const data = await Astro.request.formData();
const email = data.get("email") as string;
const password = data.get("password") as string;
// Create the admin client
const { account } = createAdminClient();
// Create the email password session
const session = await account.createEmailPasswordSession(email, password);
// Set the session cookie
Astro.cookies.set(SESSION_COOKIE, session.secret, {
path: "/",
expires: new Date(session.expires),
sameSite: "strict",
secure: true,
httpOnly: true,
});
// Redirect to the account page
return Astro.redirect("/account");
}
---
<!--- ... rest of existing form --->
```

View File

@@ -0,0 +1,50 @@
---
layout: tutorial
title: Create account page
description: Add authentication to a Astro project using Appwrite.
step: 6
---
Now the end-user is able to sign in, we can create the account page. This page will display basic information about the user, and allow the user to log out. Create a new file in the `src/pages` directory called `account.astro` and add the following code:
```js
---
import { SESSION_COOKIE, createSessionClient } from "../server/appwrite";
// Redirect the user if not signed in
const { user } = Astro.locals;
if (!user) {
return Astro.redirect("/signin");
}
// Handle form action
if (Astro.request.method === "POST") {
// Create session client
const { account } = createSessionClient(Astro.request);
// Delete the Appwrite session
await account.deleteSession("current");
// Delete the session cookie
Astro.cookies.delete(SESSION_COOKIE);
// Redirect the user to sign in page
return Astro.redirect("/signin");
}
---
<ul>
<li>
<strong>Email:</strong> {user.email}
</li>
<li>
<strong>Name:</strong> {user.name}
</li>
<li>
<strong>ID:</strong> {user.$id}
</li>
</ul>
<form method="POST">
<button type="submit">Sign out</button>
</form>
```

View File

@@ -0,0 +1,82 @@
---
layout: tutorial
title: OAuth2 authentication with SSR
description: Add authentication to a Astro project using Appwrite.
step: 7
---
To support the OAuth2 flow, we first redirect the user to the OAuth2 provider, and then handle the callback from the OAuth2 provider.
To redirect, add a button to our sign in page that redirects the user to the OAuth2 provider.
```js
<!-- src/pages/sigin.astro -->
<!-- ... existing sign in form -->
<form action="/oauth2" method="post">
<input type="hidden" name="provider" value="github" />
<button type="submit">Sign in with GitHub</button>
</form>
```
Add a new `POST` route to handle the redirect.
```js
// src/pages/oauth.js
import { createAdminClient } from "../server/appwrite";
import { OAuthProvider } from "node-appwrite";
export const POST = async ({ redirect, url }) => {
// Create the Appwrite client
const { account } = createAdminClient();
// Create an OAuth2 token
const redirectUrl = await account.createOAuth2Token(
OAuthProvider.GitHub,
`${url.protocol}//${url.hostname}/oauth`,
`${url.protocol}//${url.hostname}/signin`
);
// Redirect the end-user to the OAuth2 provider authentication
return redirect(redirectUrl);
};
```
The `createOAuth2Token` method returns a URL to the OAuth2 provider. After authentication the OAuth2 provider redirects the user back to the `/oauth2` route with the `userId` and `secret` URL query parameters.
Create a new `GET` route to handle the callback and create a session for the user.
```js
// src/pages/oauth.js
// ... existing imports
import { SESSION_COOKIE } from '$lib/server/appwrite';
// ... existing code
export const GET = async ({ cookies, redirect, url }) => {
// Extract the token data from the URL params
const userId = url.searchParams.get("userId");
const secret = url.searchParams.get("secret");
// Create the Appwrite client
const { account } = createAdminClient();
// Exchange the token data for a session
const session = await account.createSession(userId, secret);
// Set the session cookie
cookies.set(SESSION_COOKIE, session.secret, {
sameSite: "strict",
expires: new Date(session.expire),
secure: true,
httpOnly: true,
path: "/",
});
// Redirect the logged in user to the account page
return redirect("/account");
};
```

View File

@@ -0,0 +1,11 @@
---
layout: tutorial
title: All set
description: Add authentication to a Astro project using Appwrite.
step: 8
---
If you want to see the complete source code with styling, see the [demos-for-astro](https://github.com/appwrite/demos-for-astro/tree/main/server-side-rendering) repository.
# Other authentication methods {% #other-authentication-methods %}
Appwrite also supports OAuth, passwordless login, anonymous login, and phone login.
Learn more about them in the [authentication guide](https://appwrite.io/docs/products/auth).

View File

@@ -0,0 +1,11 @@
import type { LayoutLoad } from './$types';
export const load: LayoutLoad = ({ url }) => {
const tutorials = import.meta.glob('./**/*.markdoc', {
eager: true
});
return {
tutorials,
pathname: url.pathname
};
};

View File

@@ -0,0 +1,5 @@
import { redirect } from '@sveltejs/kit';
export function load() {
throw redirect(303, '/docs/tutorials/nextjs-ssr-auth/step-1');
}

View File

@@ -0,0 +1,20 @@
---
layout: tutorial
title: Server-side authentication with Next.js
description: Add SSR authentication to your Next.js app with Appwrite
step: 1
difficulty: beginner
readtime: 20
framework: Next.js SSR
category: Auth
---
Appwrite takes away the stress of building and maintaining a backend. Appwrite helps implement authentication, databases, file storage, and respond to real-time events with **secure** APIs out of the box.
If you're a Next.js developer, the examples in this guide show you how Appwrite can help you add authentication to Next.js apps faster.
# Before you start {% #before-you-start %}
Even if you've never tried Appwrite, you will get an idea of what it'll feel like to build with Next.js and Appwrite.
If you're inspired and wish to follow along, make sure you've followed [Start with React](https://appwrite.io/docs/quick-starts/react) first.
Clone the [demos-for-react](https://github.com/appwrite/demos-for-react/tree/main/nextjs) examples and follow along with the source code.

View File

@@ -0,0 +1,44 @@
---
layout: tutorial
title: Create project
description: Add authentication to a Next.js project using Appwrite.
step: 2
---
Create a project using [Next.js](https://nextjs.org/docs/getting-started/installation#automatic-installation).
```sh
npx create-next-app@latest
```
The command will give you a prompt with several project types. We'll be starting with a skeleton project.
The prompt will be something similar to this.
```sh
What is your project named? my-app
Would you like to use TypeScript? No
Would you like to use ESLint? No
Would you like to use Tailwind CSS? No
Would you like to use `src/` directory? Yes
Would you like to use App Router? (recommended) Yes
Would you like to customize the default import alias (@/*)? No
What import alias would you like configured? [Enter]
```
After the prompt is finished, you can head over to the newly create project.
```sh
cd my-app
npm install
```
# Install Appwrite {% #install-appwrite %}
Appwrite provides a Node SDK that can be used in your Next.js apps. You can use Appwrite by installing the Node SDK as an NPM package.
The Node SDK is intended for server-side use. If you want to use Appwrite in a client-side application, you should use the [Web SDK](/docs/quick-starts/web) instead.
```sh
npm install node-appwrite
```

View File

@@ -0,0 +1,99 @@
---
layout: tutorial
title: Initialize SDK
description: Add authentication to a Next.js project using Appwrite.
step: 3
---
Before you can use Appwrite, you need to create the Appwrite `Client` and set the project ID and endpoint.
The client is then used to create services like `Databases` and `Account`, so they all point to the same Appwrite project.
Create a function to build services you need in a file like `src/lib/server/appwrite.js` and **exporting the instances**.
As part of the function, set the current user's session if they are logged in. This is done by accessing the session cookie from the request and calling the `setSession(session)` with the cookie value.
{% info title="Appwrite client security" %}
Notice that `createAppwriteClient` returns **a new instance** of the Appwrite Client.
When using Appwrite in server-integrations, it's important to **never share a `Client` instance** between two requests.
Doing so could create security vulnerabilities.
{% /info %}
```js
// src/lib/server/appwrite.js
import { Client, Account } from "node-appwrite";
import { parseCookie } from "next/dist/compiled/@edge-runtime/cookies";
// The name of your cookie that will store the session
export const SESSION_COOKIE = "my-custom-session";
// Admin client, used to create new accounts
export function createAdminClient() {
const client = new Client()
.setEndpoint(import.meta.env.PUBLIC_APPWRITE_ENDPOINT)
.setProject(import.meta.env.PUBLIC_APPWRITE_PROJECT_ID)
.setKey(import.meta.env.APPWRITE_KEY); // Set the API key here!
// Return the services you need
return {
get account() {
return new Account(client);
},
};
}
// Session client, used to make requests on behalf of the logged in user
export function createSessionClient(request) {
const client = new Client()
.setEndpoint(import.meta.env.PUBLIC_APPWRITE_ENDPOINT)
.setProject(import.meta.env.PUBLIC_APPWRITE_PROJECT_ID);
// Get the session cookie from the request and set the session
const cookies = parseCookies(request.headers.get("cookie") ?? "");
const session = cookies.get(SESSION_COOKIE);
if (session) {
client.setSession(session);
}
// Return the services you need
return {
get account() {
return new Account(client);
},
};
}
```
`APPWRITE_KEY`, `NEXT_PUBLIC_APPWRITE_ENDPOINT` and `NEXT_PUBLIC_APPWRITE_PROJECT` are environment variables that are exported in your project's [.env file](https://nextjs.org/docs/app/building-your-application/configuring/environment-variables).
The `PUBLIC_APPWRITE_ENDPOINT` is the endpoint of your Appwrite project, and the `PUBLIC_APPWRITE_PROJECT` is the ID of the project you want to use.
You can get the values for these variables from the Appwrite console.
{% only_dark %}
![Create project screen](/images/docs/quick-starts/dark/create-project.png)
{% /only_dark %}
{% only_light %}
![Create project screen](/images/docs/quick-starts/create-project.png)
{% /only_light %}
The `APPWRITE_KEY` is an Appwrite API key with the necessary permissions to read and write accounts and sessions.
For this tutorial you'll need an API key with the following scopes:
| Category {% width=120 %} | Required scopes | Purpose |
|-----------|---------------------|---------|
| Sessions | `sessions.write` | Allows API key to create, update, and delete sessions. |
{% only_dark %}
![Server integrations](/images/docs/quick-starts/dark/integrate-server.png)
{% /only_dark %}
{% only_light %}
![Server integrations](/images/docs/quick-starts/integrate-server.png)
{% /only_light %}
For example, your `.env` might look something similar to this.
```text
APPWRITE_KEY=<YOUR_API_KEY>
PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
PUBLIC_APPWRITE_PROJECT=<YOUR_PROJECT_ID>
```

View File

@@ -0,0 +1,38 @@
---
layout: tutorial
title: Get the logged in user
description: Add authentication to a Next.js project using Appwrite.
step: 4
---
Build a utility function to get the logged in user from Appwrite. This function will be used in our components and routes to check if a user is logged in, and access the user's details.
Edit the `src/server/appwrite.js` file to create a new function called `getLoggedInUser`.
```js
// ... your createAppwriteClient function
export async function getLoggedInUser(account) {
try {
return await account.get();
} catch {}
}
```
Now, use the `getLoggedInUser` function in the home page to redirect based on the user's login status. Create a new file in the `app` directory called `+page.jsx`.
```js
import { createSessionClient, getLoggedInUser } from "@/lib/server/appwrite";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
export default async function Home() {
const { account } = createSessionClient(headers());
const user = await getLoggedInUser(account);
if (!user) redirect("/signin");
redirect("/account");
}
```
When a user visits the home page, they will be redirected to the sign in page if they are not logged in, or to the account page if they are logged in.

View File

@@ -0,0 +1,82 @@
---
layout: tutorial
title: Create sign in page
description: Add authentication to a Next.js project using Appwrite.
step: 5
---
We can now implement our sign in page. Create a `+page.jsx` file in the `src/app/signin` directory:
```jsx
// src/app/sigin/+page.jsx
import {
createSessionClient,
getLoggedInUser,
} from "@/lib/server/appwrite";
export default async function SignInPage() {
const { account } = createSessionClient(headers());
const user = await getLoggedInUser(account);
if (user) redirect("/account");
return (
<form action={signInWithEmail}>
<input
id="email"
name="email"
placeholder="Email"
type="email"
autoComplete="off"
/>
<input
id="password"
name="password"
placeholder="Password"
minLength={8}
type="password"
autoComplete="off"
/>
<button type="submit">Sign in</button>
</form>
);
}
```
This is an HTML form with an email and password input. When the form is submitted, we want to send the email and password to Appwrite to authenticate the user. To use Next.js form actions we create the `signInWithEmail` function in the same file:
```jsx
// src/app/sigin/+page.jsx
// previous imports ...
import { SESSION_COOKIE, createAdminClient } from "@/lib/server/appwrite";
import { cookies, headers } from "next/headers";
import { redirect } from "next/navigation";
// the SignInPage component ...
async function signInWithEmail(formData) {
"use server";
const email = formData.get("email");
const password = formData.get("password");
const { account } = createAdminClient();
const session = await account.createEmailPasswordSession(email, password);
cookies().set(SESSION_COOKIE, session.secret, {
path: "/",
httpOnly: true,
sameSite: "strict",
secure: true,
});
redirect("/account");
}
```
The `signInWithEmail` function is an async function that takes the form data as an argument. It uses the `createAdminClient` function to create an admin Appwrite client and then calls the `createEmailPasswordSession` method on the `account` object. This method takes the email and password as arguments and returns a session object. We then set the session secret in a cookie and redirect the user to the account page.

View File

@@ -0,0 +1,59 @@
---
layout: tutorial
title: Create account page
description: Add authentication to a Next.js project using Appwrite.
step: 6
---
Now the end-user is able to sign in, we can create the account page. This page will display basic information about the user, and allow the user to log out. Create a new file in the `src/app/account` directory called `page.jsx` and add the following code:
```jsx
// src/app/account/page.jsx
import {
SESSION_COOKIE,
createSessionClient,
getLoggedInUser,
} from "@/lib/server/appwrite";
import { redirect } from "next/navigation";
import { cookies, headers } from "next/headers";
async function signOut() {
"use server";
const { account } = createSessionClient(headers());
cookies().delete(SESSION_COOKIE);
await account.deleteSession("current");
redirect("/signin");
}
export default async function HomePage() {
const { account } = createSessionClient(headers());
const user = await getLoggedInUser(account);
if (!user) redirect("/signin");
return (
<>
<ul>
<li>
<strong>Email:</strong> {user.email}
</li>
<li>
<strong>Name:</strong> {user.name}
</li>
<li>
<strong>ID: </strong> {user.$id}
</li>
</ul>
<form action={signOut} method="post">
<button type="submit">Log out</button>
</form>
</>
);
}
```
This code is similar to the `signin` page, but it uses the `getLoggedInUser` function to get the user's information. If the user is not logged in, the page will redirect to the sign-in page. Again, we use Next.js form actions to execute Appwrite code on the server. This time, the `signOut` function deletes the session cookie and redirect the user to the sign-in page.

View File

@@ -0,0 +1,79 @@
---
layout: tutorial
title: OAuth2 authentication with SSR
description: Add authentication to a Next.js project using Appwrite.
step: 7
---
To support the OAuth2 flow, we first redirect the user to the OAuth2 provider, and then handle the callback from the OAuth2 provider.
Add a new server action. Navigate to `src/lib/server` and create a new file `oauth2.js`:
```js
// src/lib/server/oauth2.js
import { SESSION_COOKIE, createAdminClient } from "@/lib/server/appwrite";
import { redirect } from "next/navigation";
import { headers } from "next/headers";
import { OAuthProvider } from "node-appwrite";
async function signInWithGithub(formData) {
"use server";
const { account } = createAdminClient();
const origin = headers().get("origin");
const redirectURL = await account.createOAuth2Token(
OAuthProvider.GitHub,
`${origin}/oauth2`,
`${origin}/oauth2`,
);
return redirect(redirectURL);
};
```
The `createOAuth2Token` method redirects the user to the OAuth2 provider, and then the OAuth2 provider redirects the user back to the `/oauth2` route with the `userId` and `secret` URL query parameters.
To redirect, add a button to our sign in page that redirects the user to the OAuth2 provider.
```jsx
// src/app/signin/page.jsx
// ... existing imports
import { signInWithGithub } from "@/lib/server/oauth2";
// ... existing sign in form
<form action={signInWithGithub} method="post">
<input type="hidden" name="provider" value="github" />
<button type="submit">Sign in with GitHub</button>
</form>
```
Handle the callback and create a session for the user. Create a new Next.js server route at `src/app/oauth2/route.js`:
```js
// src/app/oauth2/route.js
import { SESSION_COOKIE, createAdminClient } from "@/lib/server/appwrite";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
export async function GET(request) {
const userId = request.nextUrl.searchParams.get("userId");
const secret = request.nextUrl.searchParams.get("secret");
const { account } = createAdminClient();
const session = await account.createSession(userId, secret);
cookies().set(SESSION_COOKIE, session.secret, {
path: "/",
httpOnly: true,
sameSite: "strict",
secure: true,
});
return NextResponse.redirect(`${request.nextUrl.origin}/account`);
}
```

View File

@@ -0,0 +1,11 @@
---
layout: tutorial
title: All set
description: Add authentication to a Next.js project using Appwrite.
step: 8
---
If you want to see the complete source code with styling, see the [demos-for-react](https://github.com/appwrite/demos-for-react/tree/main/nextjs/server-side-rendering) repository.
# Other authentication methods {% #other-authentication-methods %}
Appwrite also supports OAuth, passwordless login, anonymous login, and phone login.
Learn more about them in the [authentication guide](https://appwrite.io/docs/products/auth).

View File

@@ -0,0 +1,10 @@
<script lang="ts">
import { globToTutorial } from '$lib/utils/tutorials.js';
import { setContext } from 'svelte';
export let data;
const tutorials = globToTutorial(data);
setContext('tutorials', tutorials);
</script>
<slot />

Some files were not shown because too many files have changed in this diff Show More