Create passkey session
curl --request POST \
--url https://grid.squads.xyz/api/grid/v1/passkeys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-grid-environment: <x-grid-environment>' \
--data '
{
"metaInfo": {
"appName": "<string>",
"redirectUrl": "<string>"
},
"baseUrl": "<string>",
"sessionKey": {
"expiration": 1,
"key": "11111111111111111111111111111111"
}
}
'import requests
url = "https://grid.squads.xyz/api/grid/v1/passkeys"
payload = {
"metaInfo": {
"appName": "<string>",
"redirectUrl": "<string>"
},
"baseUrl": "<string>",
"sessionKey": {
"expiration": 1,
"key": "11111111111111111111111111111111"
}
}
headers = {
"x-grid-environment": "<x-grid-environment>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-grid-environment': '<x-grid-environment>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
metaInfo: {appName: '<string>', redirectUrl: '<string>'},
baseUrl: '<string>',
sessionKey: {expiration: 1, key: '11111111111111111111111111111111'}
})
};
fetch('https://grid.squads.xyz/api/grid/v1/passkeys', 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://grid.squads.xyz/api/grid/v1/passkeys",
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([
'metaInfo' => [
'appName' => '<string>',
'redirectUrl' => '<string>'
],
'baseUrl' => '<string>',
'sessionKey' => [
'expiration' => 1,
'key' => '11111111111111111111111111111111'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-grid-environment: <x-grid-environment>"
],
]);
$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://grid.squads.xyz/api/grid/v1/passkeys"
payload := strings.NewReader("{\n \"metaInfo\": {\n \"appName\": \"<string>\",\n \"redirectUrl\": \"<string>\"\n },\n \"baseUrl\": \"<string>\",\n \"sessionKey\": {\n \"expiration\": 1,\n \"key\": \"11111111111111111111111111111111\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-grid-environment", "<x-grid-environment>")
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://grid.squads.xyz/api/grid/v1/passkeys")
.header("x-grid-environment", "<x-grid-environment>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"metaInfo\": {\n \"appName\": \"<string>\",\n \"redirectUrl\": \"<string>\"\n },\n \"baseUrl\": \"<string>\",\n \"sessionKey\": {\n \"expiration\": 1,\n \"key\": \"11111111111111111111111111111111\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://grid.squads.xyz/api/grid/v1/passkeys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-grid-environment"] = '<x-grid-environment>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"metaInfo\": {\n \"appName\": \"<string>\",\n \"redirectUrl\": \"<string>\"\n },\n \"baseUrl\": \"<string>\",\n \"sessionKey\": {\n \"expiration\": 1,\n \"key\": \"11111111111111111111111111111111\"\n }\n}"
response = http.request(request)
puts response.read_body{
"url": "<string>"
}Passkeys
Create Passkey Session
Initialize a passkey creation session and receive a hosted UI URL for WebAuthn ceremony.
Create passkey session
curl --request POST \
--url https://grid.squads.xyz/api/grid/v1/passkeys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-grid-environment: <x-grid-environment>' \
--data '
{
"metaInfo": {
"appName": "<string>",
"redirectUrl": "<string>"
},
"baseUrl": "<string>",
"sessionKey": {
"expiration": 1,
"key": "11111111111111111111111111111111"
}
}
'import requests
url = "https://grid.squads.xyz/api/grid/v1/passkeys"
payload = {
"metaInfo": {
"appName": "<string>",
"redirectUrl": "<string>"
},
"baseUrl": "<string>",
"sessionKey": {
"expiration": 1,
"key": "11111111111111111111111111111111"
}
}
headers = {
"x-grid-environment": "<x-grid-environment>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-grid-environment': '<x-grid-environment>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
metaInfo: {appName: '<string>', redirectUrl: '<string>'},
baseUrl: '<string>',
sessionKey: {expiration: 1, key: '11111111111111111111111111111111'}
})
};
fetch('https://grid.squads.xyz/api/grid/v1/passkeys', 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://grid.squads.xyz/api/grid/v1/passkeys",
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([
'metaInfo' => [
'appName' => '<string>',
'redirectUrl' => '<string>'
],
'baseUrl' => '<string>',
'sessionKey' => [
'expiration' => 1,
'key' => '11111111111111111111111111111111'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-grid-environment: <x-grid-environment>"
],
]);
$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://grid.squads.xyz/api/grid/v1/passkeys"
payload := strings.NewReader("{\n \"metaInfo\": {\n \"appName\": \"<string>\",\n \"redirectUrl\": \"<string>\"\n },\n \"baseUrl\": \"<string>\",\n \"sessionKey\": {\n \"expiration\": 1,\n \"key\": \"11111111111111111111111111111111\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-grid-environment", "<x-grid-environment>")
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://grid.squads.xyz/api/grid/v1/passkeys")
.header("x-grid-environment", "<x-grid-environment>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"metaInfo\": {\n \"appName\": \"<string>\",\n \"redirectUrl\": \"<string>\"\n },\n \"baseUrl\": \"<string>\",\n \"sessionKey\": {\n \"expiration\": 1,\n \"key\": \"11111111111111111111111111111111\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://grid.squads.xyz/api/grid/v1/passkeys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-grid-environment"] = '<x-grid-environment>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"metaInfo\": {\n \"appName\": \"<string>\",\n \"redirectUrl\": \"<string>\"\n },\n \"baseUrl\": \"<string>\",\n \"sessionKey\": {\n \"expiration\": 1,\n \"key\": \"11111111111111111111111111111111\"\n }\n}"
response = http.request(request)
puts response.read_body{
"url": "<string>"
}The “Try It” feature is disabled for this endpoint because it initiates a WebAuthn ceremony that returns a URL. Testing requires completing the ceremony in a browser. Use the Integration Guide for implementation examples.
Key Features
- Hosted UI: Returns a pre-configured URL with embedded challenge
- Session Management: Associates session key for transaction signing
- Custom Domains: Support for custom baseUrl configuration
- Cross-Platform: Works on web, mobile, and across devices
Request Body
meta_info (required)
Configuration for the hosted UI:- appName (string): Display name shown to users during passkey creation
- redirectUrl (string, optional): URL to redirect after completion
sessionKey (optional)
Session key configuration:- key (string): Solana public key in base58 format
- expiration (number): Seconds from now until expiration (e.g., 900 for 15 minutes)
The session key format in the request uses seconds from now for
expiration, but the response returns a Unix timestamp. For example, if
you send
expiration: 900, you’ll receive back expiration: 1234567890
(current time + 900 seconds).baseUrl (optional)
- baseUrl (string): Custom domain for hosting the passkey flow (e.g.,
https://auth.yourcompany.com) - If omitted, uses the default Grid hosted UI
Response
Returns a URL for the passkey creation ceremony:{
"url": "https://passkey.grid.squads.xyz/create?challenge=..."
}
- challenge: Base64 encoded challenge for WebAuthn (valid for 60 seconds)
- slot: Solana slot number for replay protection
- Other params: Configuration for the hosted UI
Implementation Flow
1
Generate Session Key
Create a client-side session key using Solana’s Keypair.generate()
2
Call Endpoint
POST to /passkeys with meta_info and sessionKey
3
Load URL
Display the returned URL in an iframe (web) or WebBrowser (mobile)
4
Handle Completion
Listen for postMessage events with the passkey address
5
Create Smart Account
Use the passkey address to create a Grid smart account
Important Notes
- Challenge Expiration: URL is valid for 60 seconds from generation
- Session Format: Request uses relative seconds, response uses Unix timestamp
- Algorithm: Only ES256 (algorithm
-7) is supported - User Presence: WebAuthn must verify user presence
- Next Step: After successful passkey creation, use the Create Smart Account endpoint to deploy a Grid account
Error Handling
Common errors:- InvalidMetaInfo: Missing or invalid appName
- InvalidSessionKey: Malformed session key
- InvalidBaseUrl: Custom baseUrl format invalid
Related Endpoints
- Authorize Passkey Session - Authenticate with existing passkey
- Submit Passkey Session - Submit WebAuthn response
- Create Smart Account - Deploy account with passkey
Authorizations
Your Grid API key from the Grid Dashboard
Headers
Solana network environment (sandbox, devnet, mainnet)
Body
application/json
Show child attributes
Show child attributes
Grid v1 API SessionKey type that supports backward-compatible deserialization from both raw bytes array (old format) and base58 string (new format). Always serializes to base58 string format.
Show child attributes
Show child attributes
Response
Passkey session URL created successfully
Was this page helpful?