cURL
curl --request POST \
--url https://api.example.com/rpc/Trails/PrepareIntentRecovery \
--header 'Content-Type: application/json' \
--data '
{
"intentId": "<string>",
"intentAddress": "<string>",
"refundToAddress": "<string>",
"tokenAddress": "<string>"
}
'import requests
url = "https://api.example.com/rpc/Trails/PrepareIntentRecovery"
payload = {
"intentId": "<string>",
"intentAddress": "<string>",
"refundToAddress": "<string>",
"tokenAddress": "<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({
intentId: '<string>',
intentAddress: '<string>',
refundToAddress: '<string>',
tokenAddress: '<string>'
})
};
fetch('https://api.example.com/rpc/Trails/PrepareIntentRecovery', 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.example.com/rpc/Trails/PrepareIntentRecovery",
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([
'intentId' => '<string>',
'intentAddress' => '<string>',
'refundToAddress' => '<string>',
'tokenAddress' => '<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://api.example.com/rpc/Trails/PrepareIntentRecovery"
payload := strings.NewReader("{\n \"intentId\": \"<string>\",\n \"intentAddress\": \"<string>\",\n \"refundToAddress\": \"<string>\",\n \"tokenAddress\": \"<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://api.example.com/rpc/Trails/PrepareIntentRecovery")
.header("Content-Type", "application/json")
.body("{\n \"intentId\": \"<string>\",\n \"intentAddress\": \"<string>\",\n \"refundToAddress\": \"<string>\",\n \"tokenAddress\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/rpc/Trails/PrepareIntentRecovery")
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 \"intentId\": \"<string>\",\n \"intentAddress\": \"<string>\",\n \"refundToAddress\": \"<string>\",\n \"tokenAddress\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"intentId": "<string>",
"intentProtocol": "v1",
"intentAddress": "<string>",
"chainId": 123,
"intentSource": "<string>",
"payload": {},
"typedData": {},
"payloadHash": "<string>",
"recoveryTokens": [
{
"contractAddress": "<string>",
"balance": "<string>",
"balanceUsd": "<string>",
"priceUsd": "<string>",
"decimals": 123,
"chainId": 123,
"symbol": "<string>"
}
]
}{
"error": "WebrpcEndpoint",
"code": 0,
"msg": "endpoint error",
"status": 400,
"cause": "<string>"
}{
"error": "WebrpcBadResponse",
"code": -5,
"msg": "bad response",
"status": 500,
"cause": "<string>"
}Intents (Advanced)
PrepareIntentRecovery
POST
/
rpc
/
Trails
/
PrepareIntentRecovery
cURL
curl --request POST \
--url https://api.example.com/rpc/Trails/PrepareIntentRecovery \
--header 'Content-Type: application/json' \
--data '
{
"intentId": "<string>",
"intentAddress": "<string>",
"refundToAddress": "<string>",
"tokenAddress": "<string>"
}
'import requests
url = "https://api.example.com/rpc/Trails/PrepareIntentRecovery"
payload = {
"intentId": "<string>",
"intentAddress": "<string>",
"refundToAddress": "<string>",
"tokenAddress": "<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({
intentId: '<string>',
intentAddress: '<string>',
refundToAddress: '<string>',
tokenAddress: '<string>'
})
};
fetch('https://api.example.com/rpc/Trails/PrepareIntentRecovery', 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.example.com/rpc/Trails/PrepareIntentRecovery",
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([
'intentId' => '<string>',
'intentAddress' => '<string>',
'refundToAddress' => '<string>',
'tokenAddress' => '<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://api.example.com/rpc/Trails/PrepareIntentRecovery"
payload := strings.NewReader("{\n \"intentId\": \"<string>\",\n \"intentAddress\": \"<string>\",\n \"refundToAddress\": \"<string>\",\n \"tokenAddress\": \"<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://api.example.com/rpc/Trails/PrepareIntentRecovery")
.header("Content-Type", "application/json")
.body("{\n \"intentId\": \"<string>\",\n \"intentAddress\": \"<string>\",\n \"refundToAddress\": \"<string>\",\n \"tokenAddress\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/rpc/Trails/PrepareIntentRecovery")
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 \"intentId\": \"<string>\",\n \"intentAddress\": \"<string>\",\n \"refundToAddress\": \"<string>\",\n \"tokenAddress\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"intentId": "<string>",
"intentProtocol": "v1",
"intentAddress": "<string>",
"chainId": 123,
"intentSource": "<string>",
"payload": {},
"typedData": {},
"payloadHash": "<string>",
"recoveryTokens": [
{
"contractAddress": "<string>",
"balance": "<string>",
"balanceUsd": "<string>",
"priceUsd": "<string>",
"decimals": 123,
"chainId": 123,
"symbol": "<string>"
}
]
}{
"error": "WebrpcEndpoint",
"code": 0,
"msg": "endpoint error",
"status": 400,
"cause": "<string>"
}{
"error": "WebrpcBadResponse",
"code": -5,
"msg": "bad response",
"status": 500,
"cause": "<string>"
}Overview
ThePrepareIntentRecovery endpoint returns a backend-prepared payload and typed data that the user signs to recover funds stranded in an intent wallet. Combined with BuildIntentRecoveryTransaction, this endpoint enables clients to drain recoverable balances from origin or destination intent addresses after an intent has failed, expired, or otherwise left funds behind.
Use Cases
- Recover an intent’s origin deposit when the route became unfillable
- Sweep dust or leftover balances from an intent wallet
- Refund a user from a stranded intent address
Request Parameters
Required Fields
- intentId (string): The unique ID of the intent to recover.
Optional Fields
- intentAddress (string): If omitted, the backend auto-selects the origin or destination intent address by recoverable balance.
- refundToAddress (string): Defaults to the intent owner address when omitted.
- tokenAddress (string): Constrain recovery token selection when multiple recoverable tokens exist.
Response
- intentId (string)
- intentProtocol (
IntentProtocolVersion) - intentAddress (string): The intent wallet being recovered.
- chainId (number): Chain ID of the intent wallet.
- intentSource (string):
"origin"or"destination"— which intent wallet was selected for recovery. - recoveryTokens (array of
IntentTokenBalance, optional): The token balances eligible for recovery. - payload (any): Payload to be signed.
- typedData (any): EIP-712 typed data for client signing.
- payloadHash (string)
Flow
- Call
PrepareIntentRecoveryto get the payload and typed data. - Have the user sign the typed data with their wallet.
- Call
BuildIntentRecoveryTransactionwith the signed payload to receive the executable transaction. - Broadcast the transaction.
Example
const response = await fetch('https://trails-api.sequence.app/rpc/Trails/PrepareIntentRecovery', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Access-Key': 'YOUR_ACCESS_KEY'
},
body: JSON.stringify({ intentId: 'intent_abc123' })
});
const { typedData, payload, payloadHash, intentAddress } = await response.json();
// Sign typedData with the user's wallet, then continue with BuildIntentRecoveryTransaction
const signature = await walletClient.signTypedData(typedData);
Next Steps
BuildIntentRecoveryTransaction
Build the executable recovery transaction
AbortIntent
Notify Trails of an on-chain abort
Body
application/json
Response
OK
Represented as string on the server side
Available options:
v1, v1_5 []IntentTokenBalance
Show child attributes
Show child attributes
Was this page helpful?