Cancel Payment
curl --request POST \
--url https://getbill.io/external-api/v1/debts/{id}/payments/{payment_id}/cancel \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"external_cancellation_id": "<string>",
"reason": "<string>"
}
'import requests
url = "https://getbill.io/external-api/v1/debts/{id}/payments/{payment_id}/cancel"
payload = {
"external_cancellation_id": "<string>",
"reason": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({external_cancellation_id: '<string>', reason: '<string>'})
};
fetch('https://getbill.io/external-api/v1/debts/{id}/payments/{payment_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://getbill.io/external-api/v1/debts/{id}/payments/{payment_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([
'external_cancellation_id' => '<string>',
'reason' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://getbill.io/external-api/v1/debts/{id}/payments/{payment_id}/cancel"
payload := strings.NewReader("{\n \"external_cancellation_id\": \"<string>\",\n \"reason\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://getbill.io/external-api/v1/debts/{id}/payments/{payment_id}/cancel")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"external_cancellation_id\": \"<string>\",\n \"reason\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://getbill.io/external-api/v1/debts/{id}/payments/{payment_id}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"external_cancellation_id\": \"<string>\",\n \"reason\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data.status": "<string>",
"data.remaining_amount": 123,
"data.debt_paid_amount": 123,
"data.idempotent": true
}Debts API
Cancel Payment
Cancel a payment recorded through the External API
POST
/
external-api
/
v1
/
debts
/
{id}
/
payments
/
{payment_id}
/
cancel
Cancel Payment
curl --request POST \
--url https://getbill.io/external-api/v1/debts/{id}/payments/{payment_id}/cancel \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"external_cancellation_id": "<string>",
"reason": "<string>"
}
'import requests
url = "https://getbill.io/external-api/v1/debts/{id}/payments/{payment_id}/cancel"
payload = {
"external_cancellation_id": "<string>",
"reason": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({external_cancellation_id: '<string>', reason: '<string>'})
};
fetch('https://getbill.io/external-api/v1/debts/{id}/payments/{payment_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://getbill.io/external-api/v1/debts/{id}/payments/{payment_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([
'external_cancellation_id' => '<string>',
'reason' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://getbill.io/external-api/v1/debts/{id}/payments/{payment_id}/cancel"
payload := strings.NewReader("{\n \"external_cancellation_id\": \"<string>\",\n \"reason\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://getbill.io/external-api/v1/debts/{id}/payments/{payment_id}/cancel")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"external_cancellation_id\": \"<string>\",\n \"reason\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://getbill.io/external-api/v1/debts/{id}/payments/{payment_id}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"external_cancellation_id\": \"<string>\",\n \"reason\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data.status": "<string>",
"data.remaining_amount": 123,
"data.debt_paid_amount": 123,
"data.idempotent": true
}Overview
Cancels a payment previously recorded through the External API. This is a full cancellation for correcting a payment sent by mistake; partial refunds are not supported by this endpoint. Only payments created through the External API can be cancelled. Internal provider payments, such as Stripe, Scellius, PayZen, SystemPay, or SumUp payments processed by GetBill, are rejected. If the payment was attached to a payment-plan installment, the installment is moved back topending.
If the cancellation reopens a completed plan, the plan is reactivated. For a grouped plan, you may call this endpoint through any debt ID in the group; GetBill replays the remaining successful installment payments in FIFO order, so balances stay correct even when payments are cancelled out of order.
external_cancellation_id is required and used for idempotency on the payment.
Authentication
Requires a valid OAuth 2.0 access token with thedebts:write scope.
Request
string
required
Encrypted debt ID.
string
required
Payment transaction UUID returned by Record Payment or List Payments.
string
required
Partner cancellation identifier used for idempotency.
string
Optional free-form cancellation reason.
Response
string
canceled.number
Debt remaining amount after cancellation.
number
Debt paid amount after cancellation.
boolean
true when the same external_cancellation_id was already applied to this payment.Example
curl -X POST "/external-api/v1/debts/debt_id/payments/payment_uuid/cancel" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"external_cancellation_id": "partner-cancel-123",
"reason": "duplicate_payment"
}'