diff --git a/CHANGELOG.md b/CHANGELOG.md
index bef1683..e32bd1c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Change Log
+## 29.1.0
+
+* Added: `account` passkey methods `listPasskeys`, `createPasskey`, `getPasskey`, `updatePasskey`, `deletePasskey` and `updatePasskeyVerification`
+* Added: `account.createPasskeyToken` and `account.updatePasskeyToken` for passkey sign-in
+* Added: `Passkey`, `PasskeyList`, `PasskeyChallenge` and `TokenSecret` models
+
## 29.0.0
* Breaking: minimum Android SDK raised from 23 to 24 (Android 7.0)
diff --git a/README.md b/README.md
index aeffd88..535ef1f 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@ repositories {
Next, add the dependency to your project's `build.gradle(.kts)` file:
```groovy
-implementation("io.appwrite:sdk-for-android:29.0.0")
+implementation("io.appwrite:sdk-for-android:29.1.0")
```
### Maven
@@ -49,7 +49,7 @@ Add this to your project's `pom.xml` file:
io.appwrite
sdk-for-android
- 29.0.0
+ 29.1.0
```
diff --git a/docs/examples/java/account/create-passkey-token.md b/docs/examples/java/account/create-passkey-token.md
new file mode 100644
index 0000000..12db5fe
--- /dev/null
+++ b/docs/examples/java/account/create-passkey-token.md
@@ -0,0 +1,22 @@
+```java
+import android.util.Log;
+
+import io.appwrite.Client;
+import io.appwrite.coroutines.CoroutineCallback;
+import io.appwrite.services.Account;
+
+Client client = new Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject(""); // Your project ID
+
+Account account = new Account(client);
+
+account.createPasskeyToken(new CoroutineCallback<>((result, error) -> {
+ if (error != null) {
+ error.printStackTrace();
+ return;
+ }
+
+ Log.d("Appwrite", result.toString());
+}));
+```
diff --git a/docs/examples/java/account/create-passkey.md b/docs/examples/java/account/create-passkey.md
new file mode 100644
index 0000000..39a9a29
--- /dev/null
+++ b/docs/examples/java/account/create-passkey.md
@@ -0,0 +1,27 @@
+```java
+import android.util.Log;
+
+import io.appwrite.Client;
+import io.appwrite.coroutines.CoroutineCallback;
+import io.appwrite.services.Account;
+
+Client client = new Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject(""); // Your project ID
+
+Account account = new Account(client);
+
+account.createPasskey(
+ "", // passkeyId (optional)
+ "", // name (optional)
+ new CoroutineCallback<>((result, error) -> {
+ if (error != null) {
+ error.printStackTrace();
+ return;
+ }
+
+ Log.d("Appwrite", result.toString());
+ })
+);
+
+```
diff --git a/docs/examples/java/account/delete-passkey.md b/docs/examples/java/account/delete-passkey.md
new file mode 100644
index 0000000..a59d384
--- /dev/null
+++ b/docs/examples/java/account/delete-passkey.md
@@ -0,0 +1,26 @@
+```java
+import android.util.Log;
+
+import io.appwrite.Client;
+import io.appwrite.coroutines.CoroutineCallback;
+import io.appwrite.services.Account;
+
+Client client = new Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject(""); // Your project ID
+
+Account account = new Account(client);
+
+account.deletePasskey(
+ "", // passkeyId
+ new CoroutineCallback<>((result, error) -> {
+ if (error != null) {
+ error.printStackTrace();
+ return;
+ }
+
+ Log.d("Appwrite", result.toString());
+ })
+);
+
+```
diff --git a/docs/examples/java/account/get-passkey.md b/docs/examples/java/account/get-passkey.md
new file mode 100644
index 0000000..5d988e8
--- /dev/null
+++ b/docs/examples/java/account/get-passkey.md
@@ -0,0 +1,26 @@
+```java
+import android.util.Log;
+
+import io.appwrite.Client;
+import io.appwrite.coroutines.CoroutineCallback;
+import io.appwrite.services.Account;
+
+Client client = new Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject(""); // Your project ID
+
+Account account = new Account(client);
+
+account.getPasskey(
+ "", // passkeyId
+ new CoroutineCallback<>((result, error) -> {
+ if (error != null) {
+ error.printStackTrace();
+ return;
+ }
+
+ Log.d("Appwrite", result.toString());
+ })
+);
+
+```
diff --git a/docs/examples/java/account/list-passkeys.md b/docs/examples/java/account/list-passkeys.md
new file mode 100644
index 0000000..6b04b1f
--- /dev/null
+++ b/docs/examples/java/account/list-passkeys.md
@@ -0,0 +1,27 @@
+```java
+import android.util.Log;
+
+import io.appwrite.Client;
+import io.appwrite.coroutines.CoroutineCallback;
+import io.appwrite.services.Account;
+
+Client client = new Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject(""); // Your project ID
+
+Account account = new Account(client);
+
+account.listPasskeys(
+ List.of(), // queries (optional)
+ false, // total (optional)
+ new CoroutineCallback<>((result, error) -> {
+ if (error != null) {
+ error.printStackTrace();
+ return;
+ }
+
+ Log.d("Appwrite", result.toString());
+ })
+);
+
+```
diff --git a/docs/examples/java/account/update-passkey-token.md b/docs/examples/java/account/update-passkey-token.md
new file mode 100644
index 0000000..6370aaa
--- /dev/null
+++ b/docs/examples/java/account/update-passkey-token.md
@@ -0,0 +1,27 @@
+```java
+import android.util.Log;
+
+import io.appwrite.Client;
+import io.appwrite.coroutines.CoroutineCallback;
+import io.appwrite.services.Account;
+
+Client client = new Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject(""); // Your project ID
+
+Account account = new Account(client);
+
+account.updatePasskeyToken(
+ "", // challengeId
+ Map.of("a", "b"), // credential
+ new CoroutineCallback<>((result, error) -> {
+ if (error != null) {
+ error.printStackTrace();
+ return;
+ }
+
+ Log.d("Appwrite", result.toString());
+ })
+);
+
+```
diff --git a/docs/examples/java/account/update-passkey-verification.md b/docs/examples/java/account/update-passkey-verification.md
new file mode 100644
index 0000000..53eed3a
--- /dev/null
+++ b/docs/examples/java/account/update-passkey-verification.md
@@ -0,0 +1,27 @@
+```java
+import android.util.Log;
+
+import io.appwrite.Client;
+import io.appwrite.coroutines.CoroutineCallback;
+import io.appwrite.services.Account;
+
+Client client = new Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject(""); // Your project ID
+
+Account account = new Account(client);
+
+account.updatePasskeyVerification(
+ "", // passkeyId
+ Map.of("a", "b"), // credential
+ new CoroutineCallback<>((result, error) -> {
+ if (error != null) {
+ error.printStackTrace();
+ return;
+ }
+
+ Log.d("Appwrite", result.toString());
+ })
+);
+
+```
diff --git a/docs/examples/java/account/update-passkey.md b/docs/examples/java/account/update-passkey.md
new file mode 100644
index 0000000..3cf1078
--- /dev/null
+++ b/docs/examples/java/account/update-passkey.md
@@ -0,0 +1,27 @@
+```java
+import android.util.Log;
+
+import io.appwrite.Client;
+import io.appwrite.coroutines.CoroutineCallback;
+import io.appwrite.services.Account;
+
+Client client = new Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject(""); // Your project ID
+
+Account account = new Account(client);
+
+account.updatePasskey(
+ "", // passkeyId
+ "", // name
+ new CoroutineCallback<>((result, error) -> {
+ if (error != null) {
+ error.printStackTrace();
+ return;
+ }
+
+ Log.d("Appwrite", result.toString());
+ })
+);
+
+```
diff --git a/docs/examples/kotlin/account/create-passkey-token.md b/docs/examples/kotlin/account/create-passkey-token.md
new file mode 100644
index 0000000..52b6bf3
--- /dev/null
+++ b/docs/examples/kotlin/account/create-passkey-token.md
@@ -0,0 +1,13 @@
+```kotlin
+import io.appwrite.Client
+import io.appwrite.coroutines.CoroutineCallback
+import io.appwrite.services.Account
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject("") // Your project ID
+
+val account = Account(client)
+
+val result = account.createPasskeyToken()
+```
diff --git a/docs/examples/kotlin/account/create-passkey.md b/docs/examples/kotlin/account/create-passkey.md
new file mode 100644
index 0000000..69a0651
--- /dev/null
+++ b/docs/examples/kotlin/account/create-passkey.md
@@ -0,0 +1,16 @@
+```kotlin
+import io.appwrite.Client
+import io.appwrite.coroutines.CoroutineCallback
+import io.appwrite.services.Account
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject("") // Your project ID
+
+val account = Account(client)
+
+val result = account.createPasskey(
+ passkeyId = "", // (optional)
+ name = "", // (optional)
+)
+```
diff --git a/docs/examples/kotlin/account/delete-passkey.md b/docs/examples/kotlin/account/delete-passkey.md
new file mode 100644
index 0000000..08bf8fd
--- /dev/null
+++ b/docs/examples/kotlin/account/delete-passkey.md
@@ -0,0 +1,15 @@
+```kotlin
+import io.appwrite.Client
+import io.appwrite.coroutines.CoroutineCallback
+import io.appwrite.services.Account
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject("") // Your project ID
+
+val account = Account(client)
+
+val result = account.deletePasskey(
+ passkeyId = "",
+)
+```
diff --git a/docs/examples/kotlin/account/get-passkey.md b/docs/examples/kotlin/account/get-passkey.md
new file mode 100644
index 0000000..ddf9e83
--- /dev/null
+++ b/docs/examples/kotlin/account/get-passkey.md
@@ -0,0 +1,15 @@
+```kotlin
+import io.appwrite.Client
+import io.appwrite.coroutines.CoroutineCallback
+import io.appwrite.services.Account
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject("") // Your project ID
+
+val account = Account(client)
+
+val result = account.getPasskey(
+ passkeyId = "",
+)
+```
diff --git a/docs/examples/kotlin/account/list-passkeys.md b/docs/examples/kotlin/account/list-passkeys.md
new file mode 100644
index 0000000..74c8add
--- /dev/null
+++ b/docs/examples/kotlin/account/list-passkeys.md
@@ -0,0 +1,16 @@
+```kotlin
+import io.appwrite.Client
+import io.appwrite.coroutines.CoroutineCallback
+import io.appwrite.services.Account
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject("") // Your project ID
+
+val account = Account(client)
+
+val result = account.listPasskeys(
+ queries = listOf(), // (optional)
+ total = false, // (optional)
+)
+```
diff --git a/docs/examples/kotlin/account/update-passkey-token.md b/docs/examples/kotlin/account/update-passkey-token.md
new file mode 100644
index 0000000..f48e29f
--- /dev/null
+++ b/docs/examples/kotlin/account/update-passkey-token.md
@@ -0,0 +1,16 @@
+```kotlin
+import io.appwrite.Client
+import io.appwrite.coroutines.CoroutineCallback
+import io.appwrite.services.Account
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject("") // Your project ID
+
+val account = Account(client)
+
+val result = account.updatePasskeyToken(
+ challengeId = "",
+ credential = mapOf( "a" to "b" ),
+)
+```
diff --git a/docs/examples/kotlin/account/update-passkey-verification.md b/docs/examples/kotlin/account/update-passkey-verification.md
new file mode 100644
index 0000000..41c016a
--- /dev/null
+++ b/docs/examples/kotlin/account/update-passkey-verification.md
@@ -0,0 +1,16 @@
+```kotlin
+import io.appwrite.Client
+import io.appwrite.coroutines.CoroutineCallback
+import io.appwrite.services.Account
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject("") // Your project ID
+
+val account = Account(client)
+
+val result = account.updatePasskeyVerification(
+ passkeyId = "",
+ credential = mapOf( "a" to "b" ),
+)
+```
diff --git a/docs/examples/kotlin/account/update-passkey.md b/docs/examples/kotlin/account/update-passkey.md
new file mode 100644
index 0000000..c8c2bc3
--- /dev/null
+++ b/docs/examples/kotlin/account/update-passkey.md
@@ -0,0 +1,16 @@
+```kotlin
+import io.appwrite.Client
+import io.appwrite.coroutines.CoroutineCallback
+import io.appwrite.services.Account
+
+val client = Client(context)
+ .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint
+ .setProject("") // Your project ID
+
+val account = Account(client)
+
+val result = account.updatePasskey(
+ passkeyId = "",
+ name = "",
+)
+```
diff --git a/library/src/main/java/io/appwrite/Client.kt b/library/src/main/java/io/appwrite/Client.kt
index c364e83..8130478 100644
--- a/library/src/main/java/io/appwrite/Client.kt
+++ b/library/src/main/java/io/appwrite/Client.kt
@@ -101,7 +101,7 @@ class Client @JvmOverloads constructor(
"x-sdk-name" to "Android",
"x-sdk-platform" to "client",
"x-sdk-language" to "android",
- "x-sdk-version" to "29.0.0",
+ "x-sdk-version" to "29.1.0",
"x-appwrite-response-format" to "2.3.0"
)
config = mutableMapOf()
diff --git a/library/src/main/java/io/appwrite/models/Passkey.kt b/library/src/main/java/io/appwrite/models/Passkey.kt
new file mode 100644
index 0000000..de2ea0a
--- /dev/null
+++ b/library/src/main/java/io/appwrite/models/Passkey.kt
@@ -0,0 +1,61 @@
+package io.appwrite.models
+
+import com.google.gson.annotations.SerializedName
+import io.appwrite.extensions.jsonCast
+
+/**
+ * Passkey
+ */
+data class Passkey(
+ /**
+ * Passkey ID.
+ */
+ @SerializedName("\$id")
+ val id: String,
+
+ /**
+ * Passkey creation date in ISO 8601 format.
+ */
+ @SerializedName("\$createdAt")
+ val createdAt: String,
+
+ /**
+ * Passkey update date in ISO 8601 format.
+ */
+ @SerializedName("\$updatedAt")
+ val updatedAt: String,
+
+ /**
+ * Passkey name.
+ */
+ @SerializedName("name")
+ val name: String,
+
+ /**
+ * Most recent sign-in with this passkey in ISO 8601 format. Empty until the passkey is used to sign in.
+ */
+ @SerializedName("accessedAt")
+ val accessedAt: String,
+
+) {
+ fun toMap(): Map = mapOf(
+ "\$id" to id as Any,
+ "\$createdAt" to createdAt as Any,
+ "\$updatedAt" to updatedAt as Any,
+ "name" to name as Any,
+ "accessedAt" to accessedAt as Any,
+ )
+
+ companion object {
+ @Suppress("UNCHECKED_CAST")
+ fun from(
+ map: Map,
+ ) = Passkey(
+ id = map["\$id"] as String,
+ createdAt = map["\$createdAt"] as String,
+ updatedAt = map["\$updatedAt"] as String,
+ name = map["name"] as String,
+ accessedAt = map["accessedAt"] as String,
+ )
+ }
+}
diff --git a/library/src/main/java/io/appwrite/models/PasskeyChallenge.kt b/library/src/main/java/io/appwrite/models/PasskeyChallenge.kt
new file mode 100644
index 0000000..4a9f715
--- /dev/null
+++ b/library/src/main/java/io/appwrite/models/PasskeyChallenge.kt
@@ -0,0 +1,61 @@
+package io.appwrite.models
+
+import com.google.gson.annotations.SerializedName
+import io.appwrite.extensions.jsonCast
+
+/**
+ * Passkey Challenge
+ */
+data class PasskeyChallenge(
+ /**
+ * Challenge ID. When signing in, pass it back with the credential to receive a token.
+ */
+ @SerializedName("\$id")
+ val id: String,
+
+ /**
+ * Challenge creation date in ISO 8601 format.
+ */
+ @SerializedName("\$createdAt")
+ val createdAt: String,
+
+ /**
+ * ID of the passkey being registered. Empty for sign-in challenges.
+ */
+ @SerializedName("passkeyId")
+ val passkeyId: String,
+
+ /**
+ * Challenge expiration date in ISO 8601 format.
+ */
+ @SerializedName("expire")
+ val expire: String,
+
+ /**
+ * WebAuthn options in JSON form. Pass them to `PublicKeyCredential.parseCreationOptionsFromJSON()` when registering, or `PublicKeyCredential.parseRequestOptionsFromJSON()` when signing in.
+ */
+ @SerializedName("publicKey")
+ val publicKey: Map,
+
+) {
+ fun toMap(): Map = mapOf(
+ "\$id" to id as Any,
+ "\$createdAt" to createdAt as Any,
+ "passkeyId" to passkeyId as Any,
+ "expire" to expire as Any,
+ "publicKey" to publicKey as Any,
+ )
+
+ companion object {
+ @Suppress("UNCHECKED_CAST")
+ fun from(
+ map: Map,
+ ) = PasskeyChallenge(
+ id = map["\$id"] as String,
+ createdAt = map["\$createdAt"] as String,
+ passkeyId = map["passkeyId"] as String,
+ expire = map["expire"] as String,
+ publicKey = map["publicKey"] as Map,
+ )
+ }
+}
diff --git a/library/src/main/java/io/appwrite/models/PasskeyList.kt b/library/src/main/java/io/appwrite/models/PasskeyList.kt
new file mode 100644
index 0000000..3ab4efc
--- /dev/null
+++ b/library/src/main/java/io/appwrite/models/PasskeyList.kt
@@ -0,0 +1,37 @@
+package io.appwrite.models
+
+import com.google.gson.annotations.SerializedName
+import io.appwrite.extensions.jsonCast
+
+/**
+ * Passkeys List
+ */
+data class PasskeyList(
+ /**
+ * Total number of passkeys that matched your query.
+ */
+ @SerializedName("total")
+ val total: Long,
+
+ /**
+ * List of passkeys.
+ */
+ @SerializedName("passkeys")
+ val passkeys: List,
+
+) {
+ fun toMap(): Map = mapOf(
+ "total" to total as Any,
+ "passkeys" to passkeys.map { it.toMap() } as Any,
+ )
+
+ companion object {
+ @Suppress("UNCHECKED_CAST")
+ fun from(
+ map: Map,
+ ) = PasskeyList(
+ total = (map["total"] as Number).toLong(),
+ passkeys = (map["passkeys"] as List