curl --request POST \
--url https://api.next.orenda.finance/v1/auth/passkey/register/start \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-program-id: <x-program-id>' \
--data '
{
"friendly_name": "My iPhone"
}
'import requests
url = "https://api.next.orenda.finance/v1/auth/passkey/register/start"
payload = { "friendly_name": "My iPhone" }
headers = {
"x-program-id": "<x-program-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-program-id': '<x-program-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({friendly_name: 'My iPhone'})
};
fetch('https://api.next.orenda.finance/v1/auth/passkey/register/start', 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.next.orenda.finance/v1/auth/passkey/register/start",
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([
'friendly_name' => 'My iPhone'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-program-id: <x-program-id>"
],
]);
$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.next.orenda.finance/v1/auth/passkey/register/start"
payload := strings.NewReader("{\n \"friendly_name\": \"My iPhone\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-program-id", "<x-program-id>")
req.Header.Add("Authorization", "Bearer <token>")
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.next.orenda.finance/v1/auth/passkey/register/start")
.header("x-program-id", "<x-program-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"friendly_name\": \"My iPhone\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.next.orenda.finance/v1/auth/passkey/register/start")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-program-id"] = '<x-program-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"friendly_name\": \"My iPhone\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"session_token": "3f1c2e8a-9b4d-4e6f-8a1b-2c3d4e5f6a7b",
"publicKey": {
"rp": {
"id": "next.orenda.finance",
"name": "Orenda"
},
"user": {
"id": "dXNlci1jdXN0XzNmOWEyYjdl",
"name": "ada.lovelace@example.com",
"displayName": "Ada Lovelace"
},
"challenge": "q1n9bXJ0c2VjdXJlY2hhbGxlbmdl",
"pubKeyCredParams": [
{
"type": "public-key",
"alg": -7
},
{
"type": "public-key",
"alg": -257
}
],
"timeout": 120000,
"authenticatorSelection": {
"residentKey": "preferred",
"userVerification": "required"
},
"attestation": "none"
}
}
}Start adding a passkey
Step 1 of adding a passkey for a signed-in user. Returns a session_token and the publicKey options to pass to navigator.credentials.create() (or the platform credential API on iOS and Android).
On an SSO program the first call doesn’t return publicKey. It emails the user a code and responds with EMAIL_VERIFICATION_REQUIRED. Call it again with email_code to get the normal response.
For new integrations use POST /v2/auth/passkey/register/start, which takes and returns camelCase field names (sessionToken, accessToken, …). This v1 route is unchanged.
curl --request POST \
--url https://api.next.orenda.finance/v1/auth/passkey/register/start \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-program-id: <x-program-id>' \
--data '
{
"friendly_name": "My iPhone"
}
'import requests
url = "https://api.next.orenda.finance/v1/auth/passkey/register/start"
payload = { "friendly_name": "My iPhone" }
headers = {
"x-program-id": "<x-program-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-program-id': '<x-program-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({friendly_name: 'My iPhone'})
};
fetch('https://api.next.orenda.finance/v1/auth/passkey/register/start', 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.next.orenda.finance/v1/auth/passkey/register/start",
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([
'friendly_name' => 'My iPhone'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-program-id: <x-program-id>"
],
]);
$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.next.orenda.finance/v1/auth/passkey/register/start"
payload := strings.NewReader("{\n \"friendly_name\": \"My iPhone\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-program-id", "<x-program-id>")
req.Header.Add("Authorization", "Bearer <token>")
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.next.orenda.finance/v1/auth/passkey/register/start")
.header("x-program-id", "<x-program-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"friendly_name\": \"My iPhone\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.next.orenda.finance/v1/auth/passkey/register/start")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-program-id"] = '<x-program-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"friendly_name\": \"My iPhone\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"session_token": "3f1c2e8a-9b4d-4e6f-8a1b-2c3d4e5f6a7b",
"publicKey": {
"rp": {
"id": "next.orenda.finance",
"name": "Orenda"
},
"user": {
"id": "dXNlci1jdXN0XzNmOWEyYjdl",
"name": "ada.lovelace@example.com",
"displayName": "Ada Lovelace"
},
"challenge": "q1n9bXJ0c2VjdXJlY2hhbGxlbmdl",
"pubKeyCredParams": [
{
"type": "public-key",
"alg": -7
},
{
"type": "public-key",
"alg": -257
}
],
"timeout": 120000,
"authenticatorSelection": {
"residentKey": "preferred",
"userVerification": "required"
},
"attestation": "none"
}
}
}Authorizations
The user's access token from authentication (access_token on v1, accessToken on v2). The program and environment come from the token.
Headers
Identifies the program. Can also be sent as the programId query parameter.
Body
A label for this passkey, e.g. "My iPhone".