Create wallet transaction challenge
curl --request POST \
--url https://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge \
--header 'Content-Type: application/json' \
--data '
{
"wallet_pubkey": "string"
}
'import requests
url = "https://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge"
payload = { "wallet_pubkey": "string" }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({wallet_pubkey: 'string'})
};
fetch('https://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge', 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://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge",
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([
'wallet_pubkey' => 'string'
]),
CURLOPT_HTTPHEADER => [
"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://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge"
payload := strings.NewReader("{\n \"wallet_pubkey\": \"string\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge")
.header("Content-Type", "application/json")
.body("{\n \"wallet_pubkey\": \"string\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"wallet_pubkey\": \"string\"\n}"
response = http.request(request)
puts response.read_body{
"expires_at": "<string>",
"nonce_id": "<string>",
"unsigned_transaction": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}Auth
Create wallet transaction challenge
Handles POST /v1/auth/wallet/transaction-challenge via post.v1.auth.wallet.transaction_challenge.
POST
/
v1
/
auth
/
wallet
/
transaction-challenge
Create wallet transaction challenge
curl --request POST \
--url https://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge \
--header 'Content-Type: application/json' \
--data '
{
"wallet_pubkey": "string"
}
'import requests
url = "https://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge"
payload = { "wallet_pubkey": "string" }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({wallet_pubkey: 'string'})
};
fetch('https://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge', 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://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge",
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([
'wallet_pubkey' => 'string'
]),
CURLOPT_HTTPHEADER => [
"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://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge"
payload := strings.NewReader("{\n \"wallet_pubkey\": \"string\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge")
.header("Content-Type", "application/json")
.body("{\n \"wallet_pubkey\": \"string\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://perp-api.phoenix.trade/v1/auth/wallet/transaction-challenge")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"wallet_pubkey\": \"string\"\n}"
response = http.request(request)
puts response.read_body{
"expires_at": "<string>",
"nonce_id": "<string>",
"unsigned_transaction": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}Body
application/json
JSON request payload for post.v1.auth.wallet.transaction_challenge.
Response
Challenge issued
Base64-encoded unsigned Solana legacy transaction (bincode wire format) containing a single Memo program instruction that encodes the login challenge. Wallets are allowed to include additional ComputeBudget or Lighthouse instructions before signing (some inject these automatically, in arbitrary positions), but the Memo instruction, the recent blockhash, and the wallet's required-signer slot must be preserved. The transaction uses a deterministic, non-recent blockhash and is never submitted on-chain.