curl --request POST \
--url https://api.rach.finance/caas/v1/escrows/{id}/cancel \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"on_behalf_of": "BUYER",
"reason": "buyer confirmed delivery"
}
'import requests
url = "https://api.rach.finance/caas/v1/escrows/{id}/cancel"
payload = {
"on_behalf_of": "BUYER",
"reason": "buyer confirmed delivery"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({on_behalf_of: 'BUYER', reason: 'buyer confirmed delivery'})
};
fetch('https://api.rach.finance/caas/v1/escrows/{id}/cancel', 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.rach.finance/caas/v1/escrows/{id}/cancel",
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([
'on_behalf_of' => 'BUYER',
'reason' => 'buyer confirmed delivery'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <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.rach.finance/caas/v1/escrows/{id}/cancel"
payload := strings.NewReader("{\n \"on_behalf_of\": \"BUYER\",\n \"reason\": \"buyer confirmed delivery\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<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.rach.finance/caas/v1/escrows/{id}/cancel")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"on_behalf_of\": \"BUYER\",\n \"reason\": \"buyer confirmed delivery\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rach.finance/caas/v1/escrows/{id}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"on_behalf_of\": \"BUYER\",\n \"reason\": \"buyer confirmed delivery\"\n}"
response = http.request(request)
puts response.read_body{
"amount": "250000000",
"auto_release_at": "<string>",
"chain_id": 123,
"created_at": "<string>",
"dispute_reason": "<string>",
"disputed_at": "<string>",
"escrow_address": "<string>",
"funded_at": "<string>",
"funding_expires_at": "<string>",
"id": "<string>",
"network": "<string>",
"payout_pending": true,
"payout_tx_hash": "<string>",
"rail": "<string>",
"reference": "<string>",
"refunded_at": "<string>",
"released_at": "<string>",
"resolution_note": "<string>",
"state": "CREATED",
"token": "<string>",
"updated_at": "<string>"
}{}Cancel an unfunded escrow
Closes an escrow whose stored state is CREATED; FUNDED escrows cannot be cancelled. Cancellation does not transfer money. The confirmed deposit observer must report zero and be available. A late deposit can still arrive after cancellation; authorized Rach staff can recover it separately. A positive observed deposit refuses ordinary cancellation.
curl --request POST \
--url https://api.rach.finance/caas/v1/escrows/{id}/cancel \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"on_behalf_of": "BUYER",
"reason": "buyer confirmed delivery"
}
'import requests
url = "https://api.rach.finance/caas/v1/escrows/{id}/cancel"
payload = {
"on_behalf_of": "BUYER",
"reason": "buyer confirmed delivery"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({on_behalf_of: 'BUYER', reason: 'buyer confirmed delivery'})
};
fetch('https://api.rach.finance/caas/v1/escrows/{id}/cancel', 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.rach.finance/caas/v1/escrows/{id}/cancel",
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([
'on_behalf_of' => 'BUYER',
'reason' => 'buyer confirmed delivery'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <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.rach.finance/caas/v1/escrows/{id}/cancel"
payload := strings.NewReader("{\n \"on_behalf_of\": \"BUYER\",\n \"reason\": \"buyer confirmed delivery\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<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.rach.finance/caas/v1/escrows/{id}/cancel")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"on_behalf_of\": \"BUYER\",\n \"reason\": \"buyer confirmed delivery\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rach.finance/caas/v1/escrows/{id}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"on_behalf_of\": \"BUYER\",\n \"reason\": \"buyer confirmed delivery\"\n}"
response = http.request(request)
puts response.read_body{
"amount": "250000000",
"auto_release_at": "<string>",
"chain_id": 123,
"created_at": "<string>",
"dispute_reason": "<string>",
"disputed_at": "<string>",
"escrow_address": "<string>",
"funded_at": "<string>",
"funding_expires_at": "<string>",
"id": "<string>",
"network": "<string>",
"payout_pending": true,
"payout_tx_hash": "<string>",
"rail": "<string>",
"reference": "<string>",
"refunded_at": "<string>",
"released_at": "<string>",
"resolution_note": "<string>",
"state": "CREATED",
"token": "<string>",
"updated_at": "<string>"
}{}Authorizations
Your Rach B2B API key. Use rach_sk_live_* for production (on-chain) or rach_sk_test_* for sandbox (no-chain simulation).
Path Parameters
Escrow id
Body
Reason
OnBehalfOf is BUYER or SELLER when the partner is acting for one of its users. It is recorded as evidence of what the partner asserted; the authority for the action remains the partner's own and is recorded separately. Omit it when the partner is acting in its own right.
"BUYER"
Reason is required to raise a dispute and optional elsewhere. It becomes part of the escrow's permanent history.
"buyer confirmed delivery"
Response
Accepted
Amount is in base units, unlike the create request's whole-token amount. For the implemented TRON USDT adapter, "250000000" means 250 USDT.
"250000000"
AutoReleaseAt is when a funded escrow releases to the seller with no further action. Absent means it never does and someone must decide.
EscrowAddress is where the buyer sends the money. It belongs to this deal alone and is never reused.
FundingExpiresAt is when an unpaid escrow closes.
PayoutPending is true while a payout has been authorised and dispatched but not yet confirmed. Surfaced rather than hidden because during this window the honest answer to "has the seller been paid" is "not yet".
PayoutTxHash is the on-chain transaction that moved the money out. It is the partner's evidence that a release or refund really happened.
Recorded admin reasoning once a disputed payout settles.
CREATED, FUNDED, DISPUTED, RELEASED, REFUNDED, EXPIRED, CANCELLED 
