curl --request POST \
--url https://api.sandbox.brickken.com/x402/agent/transfer-ownership \
--header 'Content-Type: application/json' \
--header 'X-Payment: <api-key>' \
--data '
{
"chainId": "8453",
"newOwner": "<string>",
"executionMode": "client-signed",
"signerAddress": "<string>",
"gasLimit": "<string>",
"nonce": 123,
"privateRpcUrl": "<string>",
"ownerEmail": "jsmith@example.com",
"email": "jsmith@example.com",
"agentUuid": "<string>",
"agentId": "<string>"
}
'import requests
url = "https://api.sandbox.brickken.com/x402/agent/transfer-ownership"
payload = {
"chainId": "8453",
"newOwner": "<string>",
"executionMode": "client-signed",
"signerAddress": "<string>",
"gasLimit": "<string>",
"nonce": 123,
"privateRpcUrl": "<string>",
"ownerEmail": "jsmith@example.com",
"email": "jsmith@example.com",
"agentUuid": "<string>",
"agentId": "<string>"
}
headers = {
"X-Payment": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Payment': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
chainId: '8453',
newOwner: '<string>',
executionMode: 'client-signed',
signerAddress: '<string>',
gasLimit: '<string>',
nonce: 123,
privateRpcUrl: '<string>',
ownerEmail: 'jsmith@example.com',
email: 'jsmith@example.com',
agentUuid: '<string>',
agentId: '<string>'
})
};
fetch('https://api.sandbox.brickken.com/x402/agent/transfer-ownership', 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.sandbox.brickken.com/x402/agent/transfer-ownership",
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([
'chainId' => '8453',
'newOwner' => '<string>',
'executionMode' => 'client-signed',
'signerAddress' => '<string>',
'gasLimit' => '<string>',
'nonce' => 123,
'privateRpcUrl' => '<string>',
'ownerEmail' => 'jsmith@example.com',
'email' => 'jsmith@example.com',
'agentUuid' => '<string>',
'agentId' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Payment: <api-key>"
],
]);
$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.sandbox.brickken.com/x402/agent/transfer-ownership"
payload := strings.NewReader("{\n \"chainId\": \"8453\",\n \"newOwner\": \"<string>\",\n \"executionMode\": \"client-signed\",\n \"signerAddress\": \"<string>\",\n \"gasLimit\": \"<string>\",\n \"nonce\": 123,\n \"privateRpcUrl\": \"<string>\",\n \"ownerEmail\": \"jsmith@example.com\",\n \"email\": \"jsmith@example.com\",\n \"agentUuid\": \"<string>\",\n \"agentId\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Payment", "<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.sandbox.brickken.com/x402/agent/transfer-ownership")
.header("X-Payment", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"chainId\": \"8453\",\n \"newOwner\": \"<string>\",\n \"executionMode\": \"client-signed\",\n \"signerAddress\": \"<string>\",\n \"gasLimit\": \"<string>\",\n \"nonce\": 123,\n \"privateRpcUrl\": \"<string>\",\n \"ownerEmail\": \"jsmith@example.com\",\n \"email\": \"jsmith@example.com\",\n \"agentUuid\": \"<string>\",\n \"agentId\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.brickken.com/x402/agent/transfer-ownership")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Payment"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"chainId\": \"8453\",\n \"newOwner\": \"<string>\",\n \"executionMode\": \"client-signed\",\n \"signerAddress\": \"<string>\",\n \"gasLimit\": \"<string>\",\n \"nonce\": 123,\n \"privateRpcUrl\": \"<string>\",\n \"ownerEmail\": \"jsmith@example.com\",\n \"email\": \"jsmith@example.com\",\n \"agentUuid\": \"<string>\",\n \"agentId\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"transactions": {},
"txId": "<string>",
"info": {}
}Transfer Agent Ownership
Prepare an ERC-8004 identity ownership transfer through x402.
curl --request POST \
--url https://api.sandbox.brickken.com/x402/agent/transfer-ownership \
--header 'Content-Type: application/json' \
--header 'X-Payment: <api-key>' \
--data '
{
"chainId": "8453",
"newOwner": "<string>",
"executionMode": "client-signed",
"signerAddress": "<string>",
"gasLimit": "<string>",
"nonce": 123,
"privateRpcUrl": "<string>",
"ownerEmail": "jsmith@example.com",
"email": "jsmith@example.com",
"agentUuid": "<string>",
"agentId": "<string>"
}
'import requests
url = "https://api.sandbox.brickken.com/x402/agent/transfer-ownership"
payload = {
"chainId": "8453",
"newOwner": "<string>",
"executionMode": "client-signed",
"signerAddress": "<string>",
"gasLimit": "<string>",
"nonce": 123,
"privateRpcUrl": "<string>",
"ownerEmail": "jsmith@example.com",
"email": "jsmith@example.com",
"agentUuid": "<string>",
"agentId": "<string>"
}
headers = {
"X-Payment": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Payment': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
chainId: '8453',
newOwner: '<string>',
executionMode: 'client-signed',
signerAddress: '<string>',
gasLimit: '<string>',
nonce: 123,
privateRpcUrl: '<string>',
ownerEmail: 'jsmith@example.com',
email: 'jsmith@example.com',
agentUuid: '<string>',
agentId: '<string>'
})
};
fetch('https://api.sandbox.brickken.com/x402/agent/transfer-ownership', 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.sandbox.brickken.com/x402/agent/transfer-ownership",
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([
'chainId' => '8453',
'newOwner' => '<string>',
'executionMode' => 'client-signed',
'signerAddress' => '<string>',
'gasLimit' => '<string>',
'nonce' => 123,
'privateRpcUrl' => '<string>',
'ownerEmail' => 'jsmith@example.com',
'email' => 'jsmith@example.com',
'agentUuid' => '<string>',
'agentId' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Payment: <api-key>"
],
]);
$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.sandbox.brickken.com/x402/agent/transfer-ownership"
payload := strings.NewReader("{\n \"chainId\": \"8453\",\n \"newOwner\": \"<string>\",\n \"executionMode\": \"client-signed\",\n \"signerAddress\": \"<string>\",\n \"gasLimit\": \"<string>\",\n \"nonce\": 123,\n \"privateRpcUrl\": \"<string>\",\n \"ownerEmail\": \"jsmith@example.com\",\n \"email\": \"jsmith@example.com\",\n \"agentUuid\": \"<string>\",\n \"agentId\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Payment", "<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.sandbox.brickken.com/x402/agent/transfer-ownership")
.header("X-Payment", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"chainId\": \"8453\",\n \"newOwner\": \"<string>\",\n \"executionMode\": \"client-signed\",\n \"signerAddress\": \"<string>\",\n \"gasLimit\": \"<string>\",\n \"nonce\": 123,\n \"privateRpcUrl\": \"<string>\",\n \"ownerEmail\": \"jsmith@example.com\",\n \"email\": \"jsmith@example.com\",\n \"agentUuid\": \"<string>\",\n \"agentId\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.brickken.com/x402/agent/transfer-ownership")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Payment"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"chainId\": \"8453\",\n \"newOwner\": \"<string>\",\n \"executionMode\": \"client-signed\",\n \"signerAddress\": \"<string>\",\n \"gasLimit\": \"<string>\",\n \"nonce\": 123,\n \"privateRpcUrl\": \"<string>\",\n \"ownerEmail\": \"jsmith@example.com\",\n \"email\": \"jsmith@example.com\",\n \"agentUuid\": \"<string>\",\n \"agentId\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"transactions": {},
"txId": "<string>",
"info": {}
}safeTransferFrom that moves an ERC-8004 agent identity from Brickken custody to a wallet you control. This facade maps to agentTransferOwnership.
Call this method when you want to move custody of the identity NFT to another owner.
Authentication
Preparing charges the first half of the operation price, andPOST /send-transactions charges the rest. Each paid call answers 402 Payment Required with a PAYMENT-REQUIRED header describing the chain, asset, transfer method, amount, recipient, and timeout. Sign each payment locally and retry with X-PAYMENT.
A valid x-api-key is accepted instead of paying, on both steps.
See Authentication for the full credential matrix.
Key Fields
| Parameter | Required | Description |
|---|---|---|
chainId | Yes | Target chain ID. Use 8453 for Base mainnet or 84532 for Base Sepolia. Decimal and hex values are accepted. |
newOwner | Yes | Wallet that will receive the ERC-8004 identity NFT. Must differ from the current owner. |
agentUuid or agentId | Usually | Agent identifier from registration or the on-chain agent ID. The agent must already be registered on-chain. |
executionMode | No | client-signed (default) or client-broadcast. |
signerAddress | Yes | Wallet that signs the prepared transaction. It must be the current owner. |
Response
Returns a prepared unsigned transaction andtxId. Submit it to POST /send-transactions and complete the x402 payment.
client-signed: sign the transaction locally as the current owner, then send{ txId, signedTransactions }.
agentSetWallet, which only changes the operational wallet. After the transfer, only the new owner can perform owner-only operations for that agent.Next step
Preparing does not touch the chain. The response gives youtxId, the unsigned transactions, and an x402Requirements quote.
Choose who broadcasts
client-signed (the default) — you sign the transaction and Brickken broadcasts it. client-broadcast — you sign and broadcast it yourself, then confirm with txHash. Either way the operation price is split evenly: half at prepare, half at send.Submit it and settle the payment
POST to /send-transactions. The first attempt answers 402 Payment Required; read PAYMENT-REQUIRED, sign the payment locally, and retry with X-PAYMENT. An x-api-key is accepted here instead of paying.Poll until it confirms
GET /get-transaction-status with the txId. Your payment settles only after the operation confirms, and is released if it reverts.Authorizations
Base64-encoded x402 payment payload. Supported for x402-eligible agentic methods on /x402/... facades, /prepare-transactions, and eligible /send-transactions retries.
Body
Target operation chain ID. Use 8453 on Base mainnet or 84532 on Base Sepolia.
"8453"
"84532"
Wallet that will receive the ERC-8004 identity NFT.
^0x[a-fA-F0-9]{40}$Execution mode. Use brickken-relayed to let Brickken's relayer sign, pay gas, and broadcast (omit signerAddress). Use client-signed to sign the prepared transaction yourself.
brickken-relayed, client-signed Wallet that signs the prepared blockchain transaction. Required only in client-signed mode; omit in brickken-relayed mode.
^0x[a-fA-F0-9]{40}$Optional explicit gas limit.
Optional explicit nonce when managing nonces manually.
Optional private RPC URL override.
Optional owner attribution email.
Alias for ownerEmail where supported.
Stored tokenized agent UUID returned by agentRegister.
On-chain ERC-8004 agent ID.