Complete the Challenge
curl --request POST \
--url https://api.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue \
--header 'Client-Token: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"id": "<string>",
"rawId": "<string>",
"type": "<string>",
"response": {
"authenticatorData": "<string>",
"clientDataJSON": "<string>",
"signature": "<string>",
"userHandle": "<string>"
}
}
'import requests
url = "https://api.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue"
payload = {
"id": "<string>",
"rawId": "<string>",
"type": "<string>",
"response": {
"authenticatorData": "<string>",
"clientDataJSON": "<string>",
"signature": "<string>",
"userHandle": "<string>"
}
}
headers = {
"Client-Token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Client-Token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
id: '<string>',
rawId: '<string>',
type: '<string>',
response: {
authenticatorData: '<string>',
clientDataJSON: '<string>',
signature: '<string>',
userHandle: '<string>'
}
})
};
fetch('https://api.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue', 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.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue",
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([
'id' => '<string>',
'rawId' => '<string>',
'type' => '<string>',
'response' => [
'authenticatorData' => '<string>',
'clientDataJSON' => '<string>',
'signature' => '<string>',
'userHandle' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Client-Token: <api-key>",
"Content-Type: application/json"
],
]);
$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.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue"
payload := strings.NewReader("{\n \"id\": \"<string>\",\n \"rawId\": \"<string>\",\n \"type\": \"<string>\",\n \"response\": {\n \"authenticatorData\": \"<string>\",\n \"clientDataJSON\": \"<string>\",\n \"signature\": \"<string>\",\n \"userHandle\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Client-Token", "<api-key>")
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))
}HttpResponse<String> response = Unirest.post("https://api.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue")
.header("Client-Token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"id\": \"<string>\",\n \"rawId\": \"<string>\",\n \"type\": \"<string>\",\n \"response\": {\n \"authenticatorData\": \"<string>\",\n \"clientDataJSON\": \"<string>\",\n \"signature\": \"<string>\",\n \"userHandle\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Client-Token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"id\": \"<string>\",\n \"rawId\": \"<string>\",\n \"type\": \"<string>\",\n \"response\": {\n \"authenticatorData\": \"<string>\",\n \"clientDataJSON\": \"<string>\",\n \"signature\": \"<string>\",\n \"userHandle\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_bodyInstance
Complete the Challenge
Sends the result of the passkey resolution (WebAuthn assertion) to complete the instance connection
POST
/
instances
/
{instanceId}
/
token
/
{token}
/
passkey-prologue
Complete the Challenge
curl --request POST \
--url https://api.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue \
--header 'Client-Token: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"id": "<string>",
"rawId": "<string>",
"type": "<string>",
"response": {
"authenticatorData": "<string>",
"clientDataJSON": "<string>",
"signature": "<string>",
"userHandle": "<string>"
}
}
'import requests
url = "https://api.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue"
payload = {
"id": "<string>",
"rawId": "<string>",
"type": "<string>",
"response": {
"authenticatorData": "<string>",
"clientDataJSON": "<string>",
"signature": "<string>",
"userHandle": "<string>"
}
}
headers = {
"Client-Token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Client-Token': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
id: '<string>',
rawId: '<string>',
type: '<string>',
response: {
authenticatorData: '<string>',
clientDataJSON: '<string>',
signature: '<string>',
userHandle: '<string>'
}
})
};
fetch('https://api.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue', 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.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue",
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([
'id' => '<string>',
'rawId' => '<string>',
'type' => '<string>',
'response' => [
'authenticatorData' => '<string>',
'clientDataJSON' => '<string>',
'signature' => '<string>',
'userHandle' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Client-Token: <api-key>",
"Content-Type: application/json"
],
]);
$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.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue"
payload := strings.NewReader("{\n \"id\": \"<string>\",\n \"rawId\": \"<string>\",\n \"type\": \"<string>\",\n \"response\": {\n \"authenticatorData\": \"<string>\",\n \"clientDataJSON\": \"<string>\",\n \"signature\": \"<string>\",\n \"userHandle\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Client-Token", "<api-key>")
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))
}HttpResponse<String> response = Unirest.post("https://api.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue")
.header("Client-Token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"id\": \"<string>\",\n \"rawId\": \"<string>\",\n \"type\": \"<string>\",\n \"response\": {\n \"authenticatorData\": \"<string>\",\n \"clientDataJSON\": \"<string>\",\n \"signature\": \"<string>\",\n \"userHandle\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.z-api.io/instances/{instanceId}/token/{token}/passkey-prologue")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Client-Token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"id\": \"<string>\",\n \"rawId\": \"<string>\",\n \"type\": \"<string>\",\n \"response\": {\n \"authenticatorData\": \"<string>\",\n \"clientDataJSON\": \"<string>\",\n \"signature\": \"<string>\",\n \"userHandle\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_bodyOverview
On some devices, WhatsApp has started requiring an additional verification step when attempting to connect to WhatsApp Web, called Passkey. Because of this, devices that try to read the QR Code via the API may receive a Challenge in return.
- The QR Code endpoint is called and returns a
challenge. - This challenge is resolved on the device / authenticator (a procedure performed outside of Z-API, and that does not depend on our API).
- The result of this resolution (the WebAuthn assertion) is sent to this endpoint, so the instance can complete the connection.
The challenge resolution happens directly between the user’s device and the authenticator (Passkey), outside the Z-API ecosystem. This endpoint only receives the already processed result.With this new WhatsApp authentication in mind, Z-API created an extension called Z-API Connector, specifically to make this Passkey validation easier.
Attributes
Required
string
required
Your instance ID. Available in the Z-API panel under Instances.
string
required
Your Z-API instance token.
Required
string
required
Identifier of the credential generated by the authenticator
string
required
Raw identifier of the credential
string
required
Credential type. Always “public-key”
object
required
WebAuthn signature data returned by the authenticator
Optional
object
Client extensions returned by the authenticator
Show clientExtensionResults properties
Show clientExtensionResults properties
array
User verification methods used during the assertion
Request Body
{
"id": "...",
"rawId": "...",
"type": "public-key",
"response": {
"authenticatorData": "...",
"clientDataJSON": "...",
"signature": "...",
"userHandle": null
},
"clientExtensionResults": { "uvm": [] }
}
Response
200
Returns the result of the assertion processing by the instance. There are three possible variations: Success:{ "success": true }
{ "success": false, "reason": "assertion (rawId + response) is required" }
{ "success": false, "reason": "assertion fields must be strings" }
Responses with
success: false indicate that the assertion payload is malformed — the request body must be corrected and resent. These are not Z-API infrastructure errors.400
Returned in the following cases:- Instance not found for the
instanceId+tokenpair:
{ "error": "Instance not found", "value": null }