Cancel unpaid payment
curl --request POST \
--url https://prod-api.stableyard.fi/v2/payments/{paymentId}/cancel \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--data '
{
"reasonCode": "customer_request",
"reason": "Requested by partner"
}
'import requests
url = "https://prod-api.stableyard.fi/v2/payments/{paymentId}/cancel"
payload = {
"reasonCode": "customer_request",
"reason": "Requested by partner"
}
headers = {
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Basic <encoded-value>', 'Content-Type': 'application/json'},
body: JSON.stringify({reasonCode: 'customer_request', reason: 'Requested by partner'})
};
fetch('https://prod-api.stableyard.fi/v2/payments/{paymentId}/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://prod-api.stableyard.fi/v2/payments/{paymentId}/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([
'reasonCode' => 'customer_request',
'reason' => 'Requested by partner'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"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://prod-api.stableyard.fi/v2/payments/{paymentId}/cancel"
payload := strings.NewReader("{\n \"reasonCode\": \"customer_request\",\n \"reason\": \"Requested by partner\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Basic <encoded-value>")
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://prod-api.stableyard.fi/v2/payments/{paymentId}/cancel")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"reasonCode\": \"customer_request\",\n \"reason\": \"Requested by partner\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://prod-api.stableyard.fi/v2/payments/{paymentId}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Basic <encoded-value>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reasonCode\": \"customer_request\",\n \"reason\": \"Requested by partner\"\n}"
response = http.request(request)
puts response.read_body{
"payment": {
"id": "payment_01JY8K4Q6P9A2M7T3W5X8Z1BCR",
"apiVersion": "2026-09-09",
"intent": "receive",
"amountMode": "collect_exact",
"status": "cancelled",
"offrampStatus": null,
"stage": null,
"operationalState": "normal",
"operationalReasonCode": null,
"operationalUpdatedAt": null,
"statusVersion": 2,
"paymentAmount": {
"amount": "25.00",
"amountAtomic": "25000000",
"assetType": "crypto",
"assetCode": "USDC",
"decimals": 6,
"chainId": 42161,
"tokenAddress": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
},
"participants": [
{
"role": "recipient",
"accountId": "acct_123"
}
],
"destination": {
"type": "upa",
"accountId": "acct_123"
},
"settlement": {
"type": "settlement_destination",
"settlementDestinationId": "destination_123",
"destinationType": "connected_wallet",
"destinationAddress": "0x1111111111111111111111111111111111111111",
"chainId": 42161,
"assetCode": "USDC",
"tokenAddress": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"decimals": 6
},
"fees": {
"version": 1,
"pricingStatus": "quoted",
"platformFeeBps": 50,
"partnerFeeBps": 0,
"platformFeeAmountAtomic": "125000",
"partnerFeeAmountAtomic": "0",
"merchantNetAmountAtomic": "24875000"
},
"funding": null,
"externalReference": "order_1042",
"description": "Invoice #1042",
"metadata": {},
"expiresAt": "2026-08-28T10:10:00.000Z",
"acceptedAt": null,
"succeededAt": null,
"cancelledAt": "2026-08-28T10:02:00.000Z",
"failure": null,
"refundSummary": {
"status": "none",
"count": 0,
"requestedAmountAtomic": "0",
"confirmedAmountAtomic": "0"
},
"incidentRecoverySummary": {
"count": 0,
"pendingCount": 0,
"confirmedCount": 0,
"failedCount": 0,
"requiresInterventionCount": 0,
"requestedAmountAtomic": "0",
"confirmedAmountAtomic": "0"
},
"createdAt": "2026-08-28T10:00:00.000Z",
"updatedAt": "2026-08-28T10:02:00.000Z"
},
"nextAction": null
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}Payments
Cancel an unpaid receive payment
Cancel a receive Payment before payment is detected or escrow funds are verified.
POST
/
v2
/
payments
/
{paymentId}
/
cancel
Cancel unpaid payment
curl --request POST \
--url https://prod-api.stableyard.fi/v2/payments/{paymentId}/cancel \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--data '
{
"reasonCode": "customer_request",
"reason": "Requested by partner"
}
'import requests
url = "https://prod-api.stableyard.fi/v2/payments/{paymentId}/cancel"
payload = {
"reasonCode": "customer_request",
"reason": "Requested by partner"
}
headers = {
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Basic <encoded-value>', 'Content-Type': 'application/json'},
body: JSON.stringify({reasonCode: 'customer_request', reason: 'Requested by partner'})
};
fetch('https://prod-api.stableyard.fi/v2/payments/{paymentId}/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://prod-api.stableyard.fi/v2/payments/{paymentId}/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([
'reasonCode' => 'customer_request',
'reason' => 'Requested by partner'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"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://prod-api.stableyard.fi/v2/payments/{paymentId}/cancel"
payload := strings.NewReader("{\n \"reasonCode\": \"customer_request\",\n \"reason\": \"Requested by partner\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Basic <encoded-value>")
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://prod-api.stableyard.fi/v2/payments/{paymentId}/cancel")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"reasonCode\": \"customer_request\",\n \"reason\": \"Requested by partner\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://prod-api.stableyard.fi/v2/payments/{paymentId}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Basic <encoded-value>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reasonCode\": \"customer_request\",\n \"reason\": \"Requested by partner\"\n}"
response = http.request(request)
puts response.read_body{
"payment": {
"id": "payment_01JY8K4Q6P9A2M7T3W5X8Z1BCR",
"apiVersion": "2026-09-09",
"intent": "receive",
"amountMode": "collect_exact",
"status": "cancelled",
"offrampStatus": null,
"stage": null,
"operationalState": "normal",
"operationalReasonCode": null,
"operationalUpdatedAt": null,
"statusVersion": 2,
"paymentAmount": {
"amount": "25.00",
"amountAtomic": "25000000",
"assetType": "crypto",
"assetCode": "USDC",
"decimals": 6,
"chainId": 42161,
"tokenAddress": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
},
"participants": [
{
"role": "recipient",
"accountId": "acct_123"
}
],
"destination": {
"type": "upa",
"accountId": "acct_123"
},
"settlement": {
"type": "settlement_destination",
"settlementDestinationId": "destination_123",
"destinationType": "connected_wallet",
"destinationAddress": "0x1111111111111111111111111111111111111111",
"chainId": 42161,
"assetCode": "USDC",
"tokenAddress": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"decimals": 6
},
"fees": {
"version": 1,
"pricingStatus": "quoted",
"platformFeeBps": 50,
"partnerFeeBps": 0,
"platformFeeAmountAtomic": "125000",
"partnerFeeAmountAtomic": "0",
"merchantNetAmountAtomic": "24875000"
},
"funding": null,
"externalReference": "order_1042",
"description": "Invoice #1042",
"metadata": {},
"expiresAt": "2026-08-28T10:10:00.000Z",
"acceptedAt": null,
"succeededAt": null,
"cancelledAt": "2026-08-28T10:02:00.000Z",
"failure": null,
"refundSummary": {
"status": "none",
"count": 0,
"requestedAmountAtomic": "0",
"confirmedAmountAtomic": "0"
},
"incidentRecoverySummary": {
"count": 0,
"pendingCount": 0,
"confirmedCount": 0,
"failedCount": 0,
"requiresInterventionCount": 0,
"requestedAmountAtomic": "0",
"confirmedAmountAtomic": "0"
},
"createdAt": "2026-08-28T10:00:00.000Z",
"updatedAt": "2026-08-28T10:02:00.000Z"
},
"nextAction": null
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}{
"error": {
"code": "bad_request",
"message": "The request is invalid",
"details": "example"
}
}Cancels a receive Payment before provider detection or verified escrow funds. Send a
reasonCode (customer_request, duplicate, abandoned or other) and an optional reason. Replaying the cancel on an already-cancelled Payment returns the same Payment.
Outgoing executions cannot be cancelled until cancellation can be guaranteed safe across every payment source. See Error handling.Authorizations
HTTP Basic auth. Username is the Stableyard app ID. Password is the app secret. The optional Stableyard-Version request header must match the environment pin.
Headers
Optional contract-version assertion. Omit it to use the app environment's pinned version. A different supported version is accepted only after that environment is explicitly migrated.
Available options:
2026-09-09 Path Parameters
Canonical payment_* identifier. Internal execution identifiers are never accepted by Partner Payment routes.
Pattern:
^payment_[A-Za-z0-9_-]+$Example:
"payment_123"
Body
application/json
Response
Cancelled payment
Show child attributes
Show child attributes
The exact action the caller must complete. Null means Stableyard needs no action from the partner right now.
- Action required
- Start account KYC
- Verify UPA email
- Complete hosted compliance
- Wait for partner KYC
- Contact support
- No provider action
Show child attributes
Show child attributes
Show child attributes
Show child attributes