curl --request POST \
--url https://api.suby.fi/api/payment/{paymentId}/cancel \
--header 'Content-Type: application/json' \
--header 'X-Suby-Api-Key: <api-key>' \
--data '
{
"reason": "Replaced by a checkout with an updated prorated discount"
}
'import requests
url = "https://api.suby.fi/api/payment/{paymentId}/cancel"
payload = { "reason": "Replaced by a checkout with an updated prorated discount" }
headers = {
"X-Suby-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-Suby-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({reason: 'Replaced by a checkout with an updated prorated discount'})
};
fetch('https://api.suby.fi/api/payment/{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://api.suby.fi/api/payment/{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([
'reason' => 'Replaced by a checkout with an updated prorated discount'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Suby-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.suby.fi/api/payment/{paymentId}/cancel"
payload := strings.NewReader("{\n \"reason\": \"Replaced by a checkout with an updated prorated discount\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Suby-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.suby.fi/api/payment/{paymentId}/cancel")
.header("X-Suby-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"Replaced by a checkout with an updated prorated discount\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.suby.fi/api/payment/{paymentId}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Suby-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"Replaced by a checkout with an updated prorated discount\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "pay_abc123",
"status": "CANCELED",
"canceledAt": "2023-11-07T05:31:56Z",
"cancelReason": "<string>"
}
}{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
}{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Resource not found"
}
}{
"success": false,
"error": {
"code": "PRODUCT_NOT_FOUND",
"message": "Product not found"
}
}Cancel a checkout
Invalidates a checkout that has not settled yet. The payment moves to CANCELED, the payment link
stops loading, and no further attempt can revive it — so a superseded checkout can never be paid
alongside its replacement.
Only payments in INITIATED or PENDING can be canceled. PROCESSING is refused (a worker is
settling it), as is anything already settled, refunded or charged back — use
POST /api/refund/{paymentId} for those.
The call is idempotent: cancelling an already-canceled payment returns 200 with the original
canceledAt.
Card checkouts already handed off to the payment provider (status
PENDING) keep a live session upstream. If the buyer completes it after you cancel, Suby refuses to credit the payment and it staysCANCELED— the charge then has to be refunded on the provider side. Cancel as early as possible, ideally while the checkout is stillINITIATED.
Emits a CHECKOUT_CANCELED webhook.
curl --request POST \
--url https://api.suby.fi/api/payment/{paymentId}/cancel \
--header 'Content-Type: application/json' \
--header 'X-Suby-Api-Key: <api-key>' \
--data '
{
"reason": "Replaced by a checkout with an updated prorated discount"
}
'import requests
url = "https://api.suby.fi/api/payment/{paymentId}/cancel"
payload = { "reason": "Replaced by a checkout with an updated prorated discount" }
headers = {
"X-Suby-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-Suby-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({reason: 'Replaced by a checkout with an updated prorated discount'})
};
fetch('https://api.suby.fi/api/payment/{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://api.suby.fi/api/payment/{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([
'reason' => 'Replaced by a checkout with an updated prorated discount'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Suby-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.suby.fi/api/payment/{paymentId}/cancel"
payload := strings.NewReader("{\n \"reason\": \"Replaced by a checkout with an updated prorated discount\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Suby-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.suby.fi/api/payment/{paymentId}/cancel")
.header("X-Suby-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"Replaced by a checkout with an updated prorated discount\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.suby.fi/api/payment/{paymentId}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Suby-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"Replaced by a checkout with an updated prorated discount\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "pay_abc123",
"status": "CANCELED",
"canceledAt": "2023-11-07T05:31:56Z",
"cancelReason": "<string>"
}
}{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
}{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Resource not found"
}
}{
"success": false,
"error": {
"code": "PRODUCT_NOT_FOUND",
"message": "Product not found"
}
}Authorizations
API key authentication
Path Parameters
Body
Optional. Stored on the payment and returned on subsequent reads.
500"Replaced by a checkout with an updated prorated discount"
Was this page helpful?

