Complete passkey MFA verification
curl --request POST \
--url https://api.privy.io/v1/users/{user_id}/mfa/passkey/verification/verify \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'privy-app-id: <privy-app-id>' \
--header 'privy-user-token: <privy-user-token>' \
--data '
{
"credential": {
"id": "<string>",
"raw_id": "<string>",
"response": {
"client_data_json": "<string>",
"authenticator_data": "<string>",
"signature": "<string>",
"user_handle": "<string>"
},
"client_extension_results": {
"app_id": true,
"cred_props": {
"rk": true
},
"hmac_create_secret": true
},
"type": "public-key",
"authenticator_attachment": "<string>"
}
}
'HttpResponse<String> response = Unirest.post("https://api.privy.io/v1/users/{user_id}/mfa/passkey/verification/verify")
.header("privy-app-id", "<privy-app-id>")
.header("privy-user-token", "<privy-user-token>")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"credential\": {\n \"id\": \"<string>\",\n \"raw_id\": \"<string>\",\n \"response\": {\n \"client_data_json\": \"<string>\",\n \"authenticator_data\": \"<string>\",\n \"signature\": \"<string>\",\n \"user_handle\": \"<string>\"\n },\n \"client_extension_results\": {\n \"app_id\": true,\n \"cred_props\": {\n \"rk\": true\n },\n \"hmac_create_secret\": true\n },\n \"type\": \"public-key\",\n \"authenticator_attachment\": \"<string>\"\n }\n}")
.asString();const options = {
method: 'POST',
headers: {
'privy-app-id': '<privy-app-id>',
'privy-user-token': '<privy-user-token>',
Authorization: 'Basic <encoded-value>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
credential: {
id: '<string>',
raw_id: '<string>',
response: {
client_data_json: '<string>',
authenticator_data: '<string>',
signature: '<string>',
user_handle: '<string>'
},
client_extension_results: {app_id: true, cred_props: {rk: true}, hmac_create_secret: true},
type: 'public-key',
authenticator_attachment: '<string>'
}
})
};
fetch('https://api.privy.io/v1/users/{user_id}/mfa/passkey/verification/verify', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.privy.io/v1/users/{user_id}/mfa/passkey/verification/verify",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'credential' => [
'id' => '<string>',
'raw_id' => '<string>',
'response' => [
'client_data_json' => '<string>',
'authenticator_data' => '<string>',
'signature' => '<string>',
'user_handle' => '<string>'
],
'client_extension_results' => [
'app_id' => true,
'cred_props' => [
'rk' => true
],
'hmac_create_secret' => true
],
'type' => 'public-key',
'authenticator_attachment' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"Content-Type: application/json",
"privy-app-id: <privy-app-id>",
"privy-user-token: <privy-user-token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.privy.io/v1/users/{user_id}/mfa/passkey/verification/verify"
payload := strings.NewReader("{\n \"credential\": {\n \"id\": \"<string>\",\n \"raw_id\": \"<string>\",\n \"response\": {\n \"client_data_json\": \"<string>\",\n \"authenticator_data\": \"<string>\",\n \"signature\": \"<string>\",\n \"user_handle\": \"<string>\"\n },\n \"client_extension_results\": {\n \"app_id\": true,\n \"cred_props\": {\n \"rk\": true\n },\n \"hmac_create_secret\": true\n },\n \"type\": \"public-key\",\n \"authenticator_attachment\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("privy-app-id", "<privy-app-id>")
req.Header.Add("privy-user-token", "<privy-user-token>")
req.Header.Add("Authorization", "Basic <encoded-value>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"token": "<string>",
"expires_at": 1,
"user": {
"id": "did:privy:cm3np4u9j001rc8b73seqmqqk",
"created_at": 1731974895,
"linked_accounts": [
{
"address": "[email protected]",
"type": "email",
"first_verified_at": 1674788927,
"latest_verified_at": 1674788927,
"verified_at": 1674788927
},
{
"type": "farcaster",
"fid": 4423,
"owner_address": "0xE6bFb4137F3A8C069F98cc775f324A84FE45FdFF",
"username": "payton",
"display_name": "payton ↑",
"bio": "engineering at /privy. building pixelpool.xyz, the first Farcaster video client. nyc. 👨💻🍎🏳️🌈 nf.td/payton",
"profile_picture": "https://supercast.mypinata.cloud/ipfs/QmNexfCxdnFzWdJqKVgrjd27UGLMexNaw5FXu1XKR3cQF7?filename=IMG_2799.png",
"profile_picture_url": "https://supercast.mypinata.cloud/ipfs/QmNexfCxdnFzWdJqKVgrjd27UGLMexNaw5FXu1XKR3cQF7?filename=IMG_2799.png",
"verified_at": 1740678402,
"first_verified_at": 1740678402,
"latest_verified_at": 1741194370
},
{
"type": "passkey",
"credential_id": "Il5vP-3Tm3hNmDVBmDlREgXzIOJnZEaiVnT-XMliXe-BufP9GL1-d3qhozk9IkZwQ_",
"authenticator_name": "1Password",
"public_key": "pQECAyYgASFYIKdGwx5XxZ/7CJJzT8d5L6jyLNQdTH7X+rSZdPJ9Ux/QIlggRm4OcJ8F3aB5zYz3T9LxLdDfGpWvYkHgS4A8tPz9CqE=",
"created_with_browser": "Chrome",
"created_with_os": "Mac OS",
"created_with_device": "Macintosh",
"enrolled_in_mfa": true,
"verified_at": 1741194420,
"first_verified_at": 1741194420,
"latest_verified_at": 1741194420
}
],
"mfa_methods": [
{
"type": "passkey",
"verified_at": 1741194420
}
],
"has_accepted_terms": true,
"is_guest": false
}
}Passkey
Complete passkey MFA verification
Verifies the WebAuthn authentication response from an MFA passkey.
POST
/
v1
/
users
/
{user_id}
/
mfa
/
passkey
/
verification
/
verify
Complete passkey MFA verification
curl --request POST \
--url https://api.privy.io/v1/users/{user_id}/mfa/passkey/verification/verify \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'privy-app-id: <privy-app-id>' \
--header 'privy-user-token: <privy-user-token>' \
--data '
{
"credential": {
"id": "<string>",
"raw_id": "<string>",
"response": {
"client_data_json": "<string>",
"authenticator_data": "<string>",
"signature": "<string>",
"user_handle": "<string>"
},
"client_extension_results": {
"app_id": true,
"cred_props": {
"rk": true
},
"hmac_create_secret": true
},
"type": "public-key",
"authenticator_attachment": "<string>"
}
}
'HttpResponse<String> response = Unirest.post("https://api.privy.io/v1/users/{user_id}/mfa/passkey/verification/verify")
.header("privy-app-id", "<privy-app-id>")
.header("privy-user-token", "<privy-user-token>")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"credential\": {\n \"id\": \"<string>\",\n \"raw_id\": \"<string>\",\n \"response\": {\n \"client_data_json\": \"<string>\",\n \"authenticator_data\": \"<string>\",\n \"signature\": \"<string>\",\n \"user_handle\": \"<string>\"\n },\n \"client_extension_results\": {\n \"app_id\": true,\n \"cred_props\": {\n \"rk\": true\n },\n \"hmac_create_secret\": true\n },\n \"type\": \"public-key\",\n \"authenticator_attachment\": \"<string>\"\n }\n}")
.asString();const options = {
method: 'POST',
headers: {
'privy-app-id': '<privy-app-id>',
'privy-user-token': '<privy-user-token>',
Authorization: 'Basic <encoded-value>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
credential: {
id: '<string>',
raw_id: '<string>',
response: {
client_data_json: '<string>',
authenticator_data: '<string>',
signature: '<string>',
user_handle: '<string>'
},
client_extension_results: {app_id: true, cred_props: {rk: true}, hmac_create_secret: true},
type: 'public-key',
authenticator_attachment: '<string>'
}
})
};
fetch('https://api.privy.io/v1/users/{user_id}/mfa/passkey/verification/verify', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.privy.io/v1/users/{user_id}/mfa/passkey/verification/verify",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'credential' => [
'id' => '<string>',
'raw_id' => '<string>',
'response' => [
'client_data_json' => '<string>',
'authenticator_data' => '<string>',
'signature' => '<string>',
'user_handle' => '<string>'
],
'client_extension_results' => [
'app_id' => true,
'cred_props' => [
'rk' => true
],
'hmac_create_secret' => true
],
'type' => 'public-key',
'authenticator_attachment' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"Content-Type: application/json",
"privy-app-id: <privy-app-id>",
"privy-user-token: <privy-user-token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.privy.io/v1/users/{user_id}/mfa/passkey/verification/verify"
payload := strings.NewReader("{\n \"credential\": {\n \"id\": \"<string>\",\n \"raw_id\": \"<string>\",\n \"response\": {\n \"client_data_json\": \"<string>\",\n \"authenticator_data\": \"<string>\",\n \"signature\": \"<string>\",\n \"user_handle\": \"<string>\"\n },\n \"client_extension_results\": {\n \"app_id\": true,\n \"cred_props\": {\n \"rk\": true\n },\n \"hmac_create_secret\": true\n },\n \"type\": \"public-key\",\n \"authenticator_attachment\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("privy-app-id", "<privy-app-id>")
req.Header.Add("privy-user-token", "<privy-user-token>")
req.Header.Add("Authorization", "Basic <encoded-value>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"token": "<string>",
"expires_at": 1,
"user": {
"id": "did:privy:cm3np4u9j001rc8b73seqmqqk",
"created_at": 1731974895,
"linked_accounts": [
{
"address": "[email protected]",
"type": "email",
"first_verified_at": 1674788927,
"latest_verified_at": 1674788927,
"verified_at": 1674788927
},
{
"type": "farcaster",
"fid": 4423,
"owner_address": "0xE6bFb4137F3A8C069F98cc775f324A84FE45FdFF",
"username": "payton",
"display_name": "payton ↑",
"bio": "engineering at /privy. building pixelpool.xyz, the first Farcaster video client. nyc. 👨💻🍎🏳️🌈 nf.td/payton",
"profile_picture": "https://supercast.mypinata.cloud/ipfs/QmNexfCxdnFzWdJqKVgrjd27UGLMexNaw5FXu1XKR3cQF7?filename=IMG_2799.png",
"profile_picture_url": "https://supercast.mypinata.cloud/ipfs/QmNexfCxdnFzWdJqKVgrjd27UGLMexNaw5FXu1XKR3cQF7?filename=IMG_2799.png",
"verified_at": 1740678402,
"first_verified_at": 1740678402,
"latest_verified_at": 1741194370
},
{
"type": "passkey",
"credential_id": "Il5vP-3Tm3hNmDVBmDlREgXzIOJnZEaiVnT-XMliXe-BufP9GL1-d3qhozk9IkZwQ_",
"authenticator_name": "1Password",
"public_key": "pQECAyYgASFYIKdGwx5XxZ/7CJJzT8d5L6jyLNQdTH7X+rSZdPJ9Ux/QIlggRm4OcJ8F3aB5zYz3T9LxLdDfGpWvYkHgS4A8tPz9CqE=",
"created_with_browser": "Chrome",
"created_with_os": "Mac OS",
"created_with_device": "Macintosh",
"enrolled_in_mfa": true,
"verified_at": 1741194420,
"first_verified_at": 1741194420,
"latest_verified_at": 1741194420
}
],
"mfa_methods": [
{
"type": "passkey",
"verified_at": 1741194420
}
],
"has_accepted_terms": true,
"is_guest": false
}
}Authorizations
Basic Auth header with your app ID as the username and your app secret as the password.
Headers
ID of your Privy app.
Access token or custom authentication JWT for the user the request acts on.
Minimum string length:
1Path Parameters
Body
application/json
Completes passkey MFA verification with a WebAuthn authentication response.
WebAuthn authentication response as defined by the Web Authentication specification.
Show child attributes
Show child attributes
Response
200 - application/json
Passkey MFA verified.
An MFA token and the current user after completing an MFA ceremony.
JWT proving the user completed MFA.
Minimum string length:
1Unix timestamp in seconds when the MFA token expires.
Required range:
x >= 0A Privy user object.
Show child attributes
Show child attributes
Example:
{ "id": "did:privy:cm3np4u9j001rc8b73seqmqqk", "created_at": 1731974895, "linked_accounts": [ { "address": "[email protected]", "type": "email", "first_verified_at": 1674788927, "latest_verified_at": 1674788927, "verified_at": 1674788927 }, { "type": "farcaster", "fid": 4423, "owner_address": "0xE6bFb4137F3A8C069F98cc775f324A84FE45FdFF", "username": "payton", "display_name": "payton ↑", "bio": "engineering at /privy. building pixelpool.xyz, the first Farcaster video client. nyc. 👨💻🍎🏳️🌈 nf.td/payton", "profile_picture": "https://supercast.mypinata.cloud/ipfs/QmNexfCxdnFzWdJqKVgrjd27UGLMexNaw5FXu1XKR3cQF7?filename=IMG_2799.png", "profile_picture_url": "https://supercast.mypinata.cloud/ipfs/QmNexfCxdnFzWdJqKVgrjd27UGLMexNaw5FXu1XKR3cQF7?filename=IMG_2799.png", "verified_at": 1740678402, "first_verified_at": 1740678402, "latest_verified_at": 1741194370 }, { "type": "passkey", "credential_id": "Il5vP-3Tm3hNmDVBmDlREgXzIOJnZEaiVnT-XMliXe-BufP9GL1-d3qhozk9IkZwQ_", "authenticator_name": "1Password", "public_key": "pQECAyYgASFYIKdGwx5XxZ/7CJJzT8d5L6jyLNQdTH7X+rSZdPJ9Ux/QIlggRm4OcJ8F3aB5zYz3T9LxLdDfGpWvYkHgS4A8tPz9CqE=", "created_with_browser": "Chrome", "created_with_os": "Mac OS", "created_with_device": "Macintosh", "enrolled_in_mfa": true, "verified_at": 1741194420, "first_verified_at": 1741194420, "latest_verified_at": 1741194420 } ], "mfa_methods": [ { "type": "passkey", "verified_at": 1741194420 } ], "has_accepted_terms": true, "is_guest": false }
Was this page helpful?

