Skip to contentSkip to navigationSkip to topbar
Page toolsOn this page
Looking for more inspiration?Visit the

Verify Passkeys quickstart


(new)

Private Beta

This document could change. Twilio might add or update features before the product becomes Generally Available. Beta products don't have a Service Level Agreement (SLA). To learn more about Twilio beta support, see beta product support(link takes you to an external page).


Twilio Verify support for Passkeys

twilio-verify-support-for-passkeys page anchor

The Verify API lets you add Passkeys into your existing authentication flows. The Verify API supports Passkey registration, public key storage, and authentication flows.

Verify Passkeys offers client-side supported SDKs for iOS and Android(link takes you to an external page). This adds a low-friction, secure, cost-effective, device approval factor into your own mobile application.

Twilio belongs to the Fast IDentity Online (FIDO) alliance(link takes you to an external page) that created the Passkeys standard.


Quickstart guide: Verify Passkeys API

quickstart-guide-verify-passkeys-api page anchor

This tutorial covers Verify Passkeys service configuration and biometric Passkeys registration and authentication. This includes the following tasks:

  • Create a Verify Service for passkeys.
  • Generate a Passkey in your browser console.
  • Register a Passkey Factor on the Twilio server.
  • Save your Passkey to your password manager.
  • Create an authentication challenge from the server.
  • Sign the challenge with the Passkey and authenticate the signature of your user on the Twilio server.

To verify users at login, transaction, and other sensitive actions, follow this quickstart on Verify Passkeys.

(information)

Info

This quickstart alternates between server-side and client-side steps. To make the server-side requests, use the cURL command or an API client like Postman(link takes you to an external page). As Passkeys requests bind to specific domains requests and require user interaction, you make your requests in your browser's developer tools(link takes you to an external page).


Create Passkey-enabled Verify Service

create-passkey-enabled-verify-service page anchor

A Passkey binds to an app or website domain. During Passkey creation and challenge verification, the underlying WebAuthn API(link takes you to an external page) checks the domain in the browser URL.

To prevent issues with a production environment, create a Verify Service instance. Replace the Relying Party parameters with your application name and domains. If you like to update an existing service, check the Service API(link takes you to an external page) for more details.

POST /v2/Services

Parameters

parameters page anchor
NameTypeNecessityDescription
NameStringRequiredHuman-readable description of the Verify service. Maximum length: 255 characters.
PasskeysobjectRequiredMetadata for the Passkey.
Passkeys
.RelyingParty.id
StringRequiredRelying party identifier expressed as the origin domain without a scheme and port.
Passkeys
.RelyingParty.name
StringRequiredDescription that the authenticator displays during the registration and authentication process.
Passkeys
.RelyingParty.origins
Array[String]RequiredList of Relying Party Server Origins or App IDs that your service accepts.
Passkeys
.AuthenticatorAttachment
StringRequiredFlag that indicates a requirement to attach only to a certain type of authenticator.

Accepts: platform, cross-platform, any
Passkeys
.DiscoverableCredentials
StringRequiredFlag that indicates the level of preference for discoverable credentials.

Accepts: required, preferred, discouraged
Passkeys
.UserVerification
StringRequiredFlag that indicates whether authentication requires user identity verification.

Accepts: required, preferred, discouraged
  1. Make a request to the Services resource. Pass all required parameters.

    Create a new Passkey-enabled Verify Service request example

    create-a-new-passkey-enabled-verify-service-request-example page anchor
    1
    curl -L 'https://verify.twilio.com/v2/Services' \
    2
    -H 'Content-Type: application/x-www-form-urlencoded' \
    3
    -H 'Authorization: ••••••' \
    4
    --data-urlencode 'Name=Fancy Service' \
    5
    --data-urlencode 'Passkeys.RelyingParty.Id=example.com' \
    6
    --data-urlencode 'Passkeys.RelyingParty.Name=My domain' \
    7
    --data-urlencode 'Passkeys.RelyingParty.Origins=example.com,login.example.com' \
    8
    --data-urlencode 'Passkeys.AuthenticatorAttachment=platform' \
    9
    --data-urlencode 'Passkeys.DiscoverableCredentials=preferred' \
    10
    --data-urlencode 'Passkeys.UserVerification=preferred'
  2. If the response includes a passkeys JSON object that matches your request, you have succeeded in starting a Verify service.

    Create a new Passkey-enabled Verify Service response example

    create-a-new-passkey-enabled-verify-service-response-example page anchor
    1
    {
    2
    "sid": "VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    3
    "account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    4
    "friendly_name": "Fancy Service",
    5
    ...
    6
    "passkeys": {
    7
    "relying_party": {
    8
    "id": "example.com",
    9
    "name": "My domain",
    10
    "origins": [
    11
    "example.com",
    12
    "login.example.com"
    13
    ]
    14
    },
    15
    "authenticator_attachment": "platform",
    16
    "discoverable_credentials": "preferred",
    17
    "user_verification": "preferred"
    18
    },
    19
    ...
    20
    }

To register a Passkey, complete three tasks:

  1. On the Twilio server: Create a Passkey factor.
  2. In your browser client: Register a Passkey with the factor details
  3. On the Twilio server: Verify Passkey registration

Add a Passkey factor with the Twilio API

add-a-passkey-factor-with-the-twilio-api page anchor

A Passkey factor refers to the authentication component that the Passkey uses to verify your identity. This could be something you know, like a personal identification number (PIN), or something you have, like a fingerprint.

To start registering a Passkey, call the Twilio Factors subresource with the following parameters.

POST /v2/Services/{service_sid}/Passkeys/Factors
NameTypeNecessityDescriptionPII
friendly_nameStringRequiredHuman-readable description of the Factor. Maximum length: 255 characters.No
identityStringOptionalUnique external identifier for this Service. Your external system should generate an immutable, non-PII value between 8 and 64 characters in length. Acceptable values include your user's UUID, GUID, or SID. It can only contain hyphen (-) separated hexadecimal digits. If omitted in the request, the API creates this value.Yes
config
.authenticator_attachment
StringOptionalFlag that indicates a requirement to attach only to a certain type of authenticator.
Accepts: platform, cross-platform, any
Default: Per Service configuration
No
config
.discoverable_credentials
StringOptionalFlag that indicates the level of preference for discoverable credentials.
Accepts: required, preferred, discouraged
Default: Per Service configuration
No
config
.user_verification
StringOptionalFlag that indicates whether user identity verification is required.
Accepts: required, preferred, discouraged
Default: Per Service configuration
No
  1. Make POST request to the Factors subresource. Pass the friendly_name and identity keys and values as a JSON object payload.

    Create a new Passkey factorLink to code sample: Create a new Passkey factor
    1
    // Download the helper library from https://www.twilio.com/docs/node/install
    2
    const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
    3
    4
    // Find your Account SID and Auth Token at twilio.com/console
    5
    // and set the environment variables. See http://twil.io/secure
    6
    const accountSid = process.env.TWILIO_ACCOUNT_SID;
    7
    const authToken = process.env.TWILIO_AUTH_TOKEN;
    8
    const client = twilio(accountSid, authToken);
    9
    10
    async function createNewFactorPasskey() {
    11
    const newFactor = await client.verify.v2
    12
    .services("VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
    13
    .newFactors.create({
    14
    friendly_name: "friendly_name",
    15
    identity: "identity",
    16
    });
    17
    18
    console.log(newFactor.binding);
    19
    }
    20
    21
    createNewFactorPasskey();

    Response

    Note about this response
    1
    {
    2
    "sid": "YFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    3
    "account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    4
    "service_sid": "VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    5
    "entity_sid": "YEaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    6
    "identity": "identity",
    7
    "binding": null,
    8
    "date_created": "2015-07-30T20:00:00Z",
    9
    "date_updated": "2015-07-30T20:00:00Z",
    10
    "friendly_name": "friendly_name",
    11
    "status": "unverified",
    12
    "factor_type": "passkeys",
    13
    "config": {
    14
    "relying_party": {
    15
    "id": "example.com",
    16
    "name": "Example",
    17
    "origins": [
    18
    "https://example.com"
    19
    ]
    20
    },
    21
    "authenticator_attachment": "platform",
    22
    "discoverable_credentials": "preferred",
    23
    "user_verification": "preferred"
    24
    },
    25
    "options": {
    26
    "publicKey": {
    27
    "rp": {
    28
    "id": "example.com",
    29
    "name": "Example"
    30
    },
    31
    "user": {
    32
    "id": "WUU0ZmQzYWFmNGU0NTMyNGQwZjNlMTM0NjA3YjIxOTEyYg",
    33
    "name": "friendly_name",
    34
    "displayName": "friendly_name"
    35
    },
    36
    "challenge": "WUYwNDhkMWE3ZWMzYTJhNjk3MDA1OWMyNzY2YmJjN2UwZg",
    37
    "pubKeyCredParams": {
    38
    "type": "public-key",
    39
    "alg": -7
    40
    },
    41
    "timeout": 600000,
    42
    "excludeCredentials": [],
    43
    "authenticatorSelection": {
    44
    "authenticatorAttachment": "platform",
    45
    "requireResidentKey": false,
    46
    "residentKey": "preferred",
    47
    "userVerification": "preferred"
    48
    },
    49
    "attestation": "none"
    50
    }
    51
    },
    52
    "metadata": null,
    53
    "url": "https://verify.twilio.com/v2/Services/VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Entities/ff483d1ff591898a9942916050d2ca3f/Factors/YFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    54
    }
  2. Copy the entire response. This JSON object becomes the option variable value in the Set the Passkey factor response as a variable example.

Create Passkey in your browser

create-passkey-in-your-browser page anchor

To create a Passkey in your browser, pass the entire Create a Passkey factor response example into your browser console.

  1. Open your browser.

  2. Go to the domain returned in config.relying_party.id in the Create a Passkey factor response example.

  3. Open the browser's developer tools and open your browser console. Perform the remaining steps in the browser console.

  4. Paste the following code into the console to load the webauthn-json library.

    Load the webauthn-json library

    load-the-webauthn-json-library page anchor
    1
    const { create, get, parseCreationOptionsFromJSON, parseRequestOptionsFromJSON, supported } = await
    2
    import('https://cdn.jsdelivr.net/npm/@github/webauthn-json/dist/esm/webauthn-json.browser-ponyfill.js')
  5. Create a variable to store the entire Create a Passkey factor response example, then paste the response as that variable's value.

    Set the Passkey factor response as a variable

    set-the-passkey-factor-response-as-a-variable page anchor
    let { options } = '<paste the entire Create a Passkey factor response example>';
  6. Copy the following code.

    Create a Passkey request example

    create-a-passkey-request-example page anchor
    1
    // converts challenge and user.id to ArrayBuffers
    2
    let creationOptions = parseCreationOptionsFromJSON(options);
    3
    // wrapper for navigator.credentials.create
    4
    let credential = await create(creationOptions);
  7. Paste the code into your browser console then execute it. This generates a Passkey credential.

  8. Follow the prompts in your browser to register a Passkey with the password manager of your choice.

  9. Copy the JSON response body to your clipboard with the following command.

    Copy generated credentials to clipboard

    copy-generated-credentials-to-clipboard page anchor
    copy(credential);

Verify the Passkey factor with the Twilio API

verify-the-passkey-factor-with-the-twilio-api page anchor

To finish registering the Passkey, pass the copied credential as a JSON object to the VerifyFactor subresource.

POST /v2/Services/{service_sid}/Passkeys/VerifyFactor
NameTypeNecessityDescriptionPII
idStringRequiredBase64-encoded, URL-safe(link takes you to an external page) representation of keyId.No
keyIdStringRequiredGlobally unique identifier for this PublicKeyCredential.No
authenticatorAttachmentStringRequiredMechanism by which the WebAuthn implementation is attached to the authenticator at the time the associated create(parseCreationOptionsFromJSON())(link takes you to an external page) or get(parseRequestOptionsFromJSON())(link takes you to an external page) call completes.

Accepts: platform, cross-platform
No
typeStringRequiredCredential types the API supports. These values version the AuthenticatorAssertion and AuthenticatorAttestation structures according to the type of the authenticator.

Accepts: public-key
No
responseobjectRequiredResult of a WebAuthn credential registration as specified in AuthenticatorAttestationResponse.No
response
.clientDataJSON
StringRequiredJSON-compatible serialization of the data passed from the browser to the authenticator that generated this credential.No
response
.attestationObject
StringRequiredAuthenticator data and an attestation statement for a new key pair that the authenticator generated.No
response
.transports
Array[String]OptionalHints as to the methods the client could use to communicate with the relevant authenticator of the public key credential to retrieve.

Accepts: usb, nfc, ble, smart-card, internal, hybrid
No
  1. Make a POST request to the VerifyFactor subresource. Pass the properties of the credential you copied from your browser console as a JSON object payload.

    1
    // Download the helper library from https://www.twilio.com/docs/node/install
    2
    const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
    3
    4
    // Find your Account SID and Auth Token at twilio.com/console
    5
    // and set the environment variables. See http://twil.io/secure
    6
    const accountSid = process.env.TWILIO_ACCOUNT_SID;
    7
    const authToken = process.env.TWILIO_AUTH_TOKEN;
    8
    const client = twilio(accountSid, authToken);
    9
    10
    async function updatePasskeysFactor() {
    11
    const newVerifyFactor = await client.verify.v2
    12
    .services("VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
    13
    .newVerifyFactors.update({
    14
    id: "iYCpoVaY3omxc8twDSNEaF4JjVlvbvjOgQGV",
    15
    response: {
    16
    attestationObject: "attestationObject",
    17
    clientDataJSON: "clientDataJSON",
    18
    transports: ["usb"],
    19
    },
    20
    });
    21
    22
    console.log(newVerifyFactor.sid);
    23
    }
    24
    25
    updatePasskeysFactor();

    Response

    Note about this response
    1
    {
    2
    "sid": "YFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    3
    "account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    4
    "service_sid": "VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    5
    "entity_sid": "YEaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    6
    "identity": "ff483d1ff591898a9942916050d2ca3f",
    7
    "date_created": "2015-07-30T20:00:00Z",
    8
    "date_updated": "2015-07-30T20:00:00Z",
    9
    "friendly_name": "friendly_name",
    10
    "status": "verified",
    11
    "factor_type": "passkeys",
    12
    "config": {
    13
    "relying_party": {
    14
    "id": "example.com",
    15
    "name": "Example",
    16
    "origins": [
    17
    "https://example.com"
    18
    ]
    19
    },
    20
    "authenticator_attachment": "platform",
    21
    "discoverable_credentials": "preferred",
    22
    "user_verification": "preferred"
    23
    },
    24
    "metadata": null,
    25
    "url": "https://verify.twilio.com/v2/Services/VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Entities/ff483d1ff591898a9942916050d2ca3f/Factors/YFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    26
    }
  2. If the response returns "status": "verified", you have succeeded in creating and verifying a Passkey.


Authenticate with your Passkey

authenticate-with-your-passkey page anchor

To authenticate with your Passkey, complete three tasks:

  1. On the Twilio server: Create an authentication challenge.
  2. In your browser client: Fetch the Passkey with the challenge data. The browser signs the challenge with the Passkey.
  3. On the Twilio server: Validate the signature and approve the authentication challenge.

Create a Passkey authentication challenge with the Twilio API

create-a-passkey-authentication-challenge-with-the-twilio-api page anchor
POST /v2/Services/{service_sid}/Passkeys/Challenges
NameTypeNecessityDescriptionPII
identityStringRequiredUnique identifier for a person or end user.Yes
  1. Make a POST request to the Challenges subresource. Use the same identity value from creating the Passkey factor.

    1
    // Download the helper library from https://www.twilio.com/docs/node/install
    2
    const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
    3
    4
    // Find your Account SID and Auth Token at twilio.com/console
    5
    // and set the environment variables. See http://twil.io/secure
    6
    const accountSid = process.env.TWILIO_ACCOUNT_SID;
    7
    const authToken = process.env.TWILIO_AUTH_TOKEN;
    8
    const client = twilio(accountSid, authToken);
    9
    10
    async function createChallengePasskeys() {
    11
    const newChallenge = await client.verify.v2
    12
    .services("VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
    13
    .newChallenge()
    14
    .create({
    15
    identity: "identity",
    16
    });
    17
    18
    console.log(newChallenge.options);
    19
    }
    20
    21
    createChallengePasskeys();

    Response

    Note about this response
    1
    {
    2
    "sid": "YCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    3
    "account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    4
    "service_sid": "VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    5
    "entity_sid": "",
    6
    "identity": "identity",
    7
    "factor_sid": "",
    8
    "factor_type": "passkeys",
    9
    "status": "pending",
    10
    "date_created": "2025-07-30T20:00:00Z",
    11
    "date_updated": "2025-07-30T20:00:00Z",
    12
    "date_responded": null,
    13
    "details": null,
    14
    "expiration_date": null,
    15
    "hidden_details": null,
    16
    "links": null,
    17
    "metadata": null,
    18
    "responded_reason": "none",
    19
    "url": "https://verify.twilio.com/v2/Services/VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Passkeys/Challenges",
    20
    "options": {
    21
    "publicKey": {
    22
    "rp": {
    23
    "id": "example.com",
    24
    "name": "Example"
    25
    },
    26
    "user": {
    27
    "id": "WUU0ZmQzYWFmNGU0NTMyNGQwZjNlMTM0NjA3YjIxOTEyYg",
    28
    "name": "friendly_name",
    29
    "displayName": "friendly_name"
    30
    },
    31
    "challenge": "WUYwNDhkMWE3ZWMzYTJhNjk3MDA1OWMyNzY2YmJjN2UwZg",
    32
    "pubKeyCredParams": {
    33
    "type": "public-key",
    34
    "alg": -7
    35
    },
    36
    "timeout": 600000,
    37
    "excludeCredentials": [],
    38
    "authenticatorSelection": {
    39
    "authenticatorAttachment": "platform",
    40
    "requireResidentKey": false,
    41
    "residentKey": "preferred",
    42
    "userVerification": "preferred"
    43
    },
    44
    "attestation": "none"
    45
    }
    46
    }
    47
    }
  2. Copy the response for use in the Fetch the Passkey from your browser section.

Fetch the Passkey from your browser

fetch-the-passkey-from-your-browser page anchor

To fetch the Passkey from your browser, pass the entire response from the Create a Passkey authentication challenge response example into your browser console.

This requires using the same browser session. If you closed the browser console, open a new one, then reload the webauthn-json helper functions.

  1. Open your browser.

  2. Go to the domain found in publicKey.rpid in the Create a Passkey authentication challenge response example.

  3. Open the browser's developer tools and open your browser console. Perform the remaining steps in the browser console.

  4. Create a variable to store the entire Create a Passkey authentication challenge response example, then paste the response as that variable's value.

    Set the Passkey challenge response as a variable

    set-the-passkey-challenge-response-as-a-variable page anchor
    let { options } = '<paste the entire Create a Passkey authentication challenge response example>';
  5. Copy the following code.

    Fetch the Passkey request example

    fetch-the-passkey-request-example page anchor
    1
    // converts challenge and user.id to ArrayBuffers
    2
    let requestOptions = parseRequestOptionsFromJSON(options);
    3
    // wrapper for navigator.credentials.create
    4
    let credential = await get(requestOptions);
  6. Paste the code into your browser console then execute it. This generates a credential that needs server-side validation.

  7. Follow the prompts from your password manager.

  8. Copy the JSON response body to your clipboard with the following command.

    Copy fetched credentials to clipboard

    copy-fetched-credentials-to-clipboard page anchor
    copy(credential);

Approve the Passkey challenge with the Twilio API

approve-the-passkey-challenge-with-the-twilio-api page anchor

To finish authenticating your Passkey challenge, pass the response from the Fetch the Passkey request example request as a JSON object to the ApproveChallenge subresource.

POST /v2/Services/{service_sid}/Passkeys/ApproveChallenge
NameTypeNecessityDescriptionPII
idStringRequiredBase64-encoded, URL-safe(link takes you to an external page) representation of keyId.No
keyIdStringRequiredGlobally unique identifier for this PublicKeyCredential.No
authenticatorAttachmentStringOptionalMechanism by which the WebAuthn implementation attaches to the authenticator at the time the associated create(parseCreationOptionsFromJSON())(link takes you to an external page) or get(parseRequestOptionsFromJSON())(link takes you to an external page) call completes.

Accepts: platform, cross-platform
No
typeStringRequiredCredential types the API supports. These values version the AuthenticatorAssertion and AuthenticatorAttestation structures according to the type of the authenticator.

Accepts: public-key
No
responseobjectRequiredResult of a WebAuthn credential registration as specified in AuthenticatorAttestationResponse.No
response
.clientDataJSON
StringOptionalJSON-compatible serialization of the data passed from the browser to the authenticator that generated this credential.No
response
.signature
StringOptionalAssertion signature over authenticatorData and clientDataJSON.No
response
.userHandle
StringOptionalUser handle stored in the authenticator as a Base64-encoded, URL-safe(link takes you to an external page) contact ID.No
response
.authenticatorData
StringOptionalSerialized data encoded in the Client to Authenticator Protocol (CTAP2) canonical Concise Binary Object Representation (CBOR) encoding form.No
  1. Make a POST request to the ApproveChallenge subresource. Pass the properties of the credential you copied from your browser console as a JSON object payload.

    1
    // Download the helper library from https://www.twilio.com/docs/node/install
    2
    const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
    3
    4
    // Find your Account SID and Auth Token at twilio.com/console
    5
    // and set the environment variables. See http://twil.io/secure
    6
    const accountSid = process.env.TWILIO_ACCOUNT_SID;
    7
    const authToken = process.env.TWILIO_AUTH_TOKEN;
    8
    const client = twilio(accountSid, authToken);
    9
    10
    async function updateChallengePasskeys() {
    11
    const approveChallenge = await client.verify.v2
    12
    .services("VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
    13
    .approveChallenge.update({
    14
    id: "fr4561ff591898a9942916050d2ca3f",
    15
    rawId: "rawId",
    16
    authenticatorAttachment: "platform",
    17
    response: {
    18
    authenticatorData: "authenticatorData",
    19
    clientDataJSON: "clientDataJSON",
    20
    signature: "signature",
    21
    userHandle: "userHandle",
    22
    },
    23
    });
    24
    25
    console.log(approveChallenge.options);
    26
    }
    27
    28
    updateChallengePasskeys();

    Response

    Note about this response
    1
    {
    2
    "sid": "YCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    3
    "account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    4
    "service_sid": "VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    5
    "entity_sid": "",
    6
    "identity": "",
    7
    "factor_sid": "",
    8
    "factor_type": "passkeys",
    9
    "status": "approved",
    10
    "date_created": "2025-07-30T20:00:00Z",
    11
    "date_updated": "2025-07-30T20:00:00Z",
    12
    "date_responded": null,
    13
    "details": null,
    14
    "expiration_date": null,
    15
    "hidden_details": null,
    16
    "links": null,
    17
    "metadata": null,
    18
    "responded_reason": "none",
    19
    "url": "https://verify.twilio.com/v2/Services/VAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Passkeys/ApproveChallenge",
    20
    "options": {
    21
    "publicKey": {
    22
    "rp": {
    23
    "id": "example.com",
    24
    "name": "Example"
    25
    },
    26
    "user": {
    27
    "id": "WUU0ZmQzYWFmNGU0NTMyNGQwZjNlMTM0NjA3YjIxOTEyYg",
    28
    "name": "friendly_name",
    29
    "displayName": "friendly_name"
    30
    },
    31
    "challenge": "WUYwNDhkMWE3ZWMzYTJhNjk3MDA1OWMyNzY2YmJjN2UwZg",
    32
    "pubKeyCredParams": {
    33
    "type": "public-key",
    34
    "alg": -7
    35
    },
    36
    "timeout": 600000,
    37
    "excludeCredentials": [],
    38
    "authenticatorSelection": {
    39
    "authenticatorAttachment": "platform",
    40
    "requireResidentKey": false,
    41
    "residentKey": "preferred",
    42
    "userVerification": "preferred"
    43
    },
    44
    "attestation": "none"
    45
    }
    46
    }
    47
    }
  2. If the response returns "status": "approved", you have succeeded in creating and verifying a Passkey.