Cancel Payment Link
Cancel an active payment link to prevent it from being used. Only links with active status can be cancelled.
Authentication
Authorization: Bearer glm_test_YOUR_API_KEY
Path Parameters
Parameter Type Required Description idstring Yes Payment link ID (e.g., plink_abc123xyz)
Request Body
{
"reason" : "Customer requested cancellation"
}
Parameter Type Required Description reasonstring No Reason for cancellation (max 500 chars)
Request
POST /v2/payment-links/{id}/cancel
Response
{
"id" : "plink_abc123xyz" ,
"url" : "https://checkout.withgale.com/pay/plink_abc123xyz" ,
"amount_cents" : 4995 ,
"currency" : "USD" ,
"description" : "Premium Blood Pressure Monitor" ,
"payment_type" : "one_time" ,
"status" : "cancelled" ,
"customer" : {
"email" : "customer@example.com" ,
"first_name" : "Jane" ,
"last_name" : "Doe"
},
"success_url" : "https://yoursite.com/success" ,
"cancel_url" : "https://yoursite.com/cancel" ,
"metadata" : {
"order_id" : "ORD-12345"
},
"expires_at" : "2025-11-02T14:30:00Z" ,
"created_at" : "2025-10-18T14:30:00Z" ,
"cancelled_at" : "2025-10-18T16:00:00Z" ,
"cancellation_reason" : "Customer requested cancellation"
}
Response Fields
Field Type Description statusenum Will be cancelled cancelled_attimestamp When link was cancelled cancellation_reasonstring Reason provided for cancellation
All other fields match the standard payment link object.
Examples
Basic Cancellation
curl -X POST https://api.withgale.com/v2/payment-links/plink_abc123xyz/cancel \
-H "Authorization: Bearer glm_test_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Order cancelled by customer"
}'
With JavaScript
const cancelPaymentLink = async ( linkId , reason ) => {
const response = await fetch (
`https://api.withgale.com/v2/payment-links/ ${ linkId } /cancel` ,
{
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ process . env . GALE_API_KEY } ` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ reason })
}
);
if ( ! response . ok ) {
throw new Error ( 'Failed to cancel payment link' );
}
const link = await response . json ();
console . log ( `Link cancelled at ${ link . cancelled_at } ` );
return link ;
};
// Usage
await cancelPaymentLink ( 'plink_abc123xyz' , 'Customer changed mind' );
Without Reason
curl -X POST https://api.withgale.com/v2/payment-links/plink_abc123xyz/cancel \
-H "Authorization: Bearer glm_test_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
Use Cases
Customer Cancellation Request
// Allow customer to cancel pending payment
app . post ( '/orders/:linkId/cancel' , async ( req , res ) => {
try {
// Verify customer owns this link
const link = await getPaymentLink ( req . params . linkId );
if ( link . customer . email !== req . user . email ) {
return res . status ( 403 ). json ({ error: 'Unauthorized' });
}
if ( link . status !== 'active' ) {
return res . status ( 400 ). json ({
error: `Cannot cancel ${ link . status } payment link`
});
}
// Cancel the link
await cancelPaymentLink ( req . params . linkId , 'Customer requested cancellation' );
res . json ({ message: 'Payment link cancelled' });
} catch ( error ) {
res . status ( 500 ). json ({ error: error . message });
}
});
Expired Link Cleanup
// Cancel old active links that are about to expire
const cleanupOldLinks = async () => {
const links = await listPaymentLinks ({
status: 'active' ,
created_before: new Date ( Date . now () - 14 * 24 * 60 * 60 * 1000 ) // 14 days ago
});
for ( const link of links . data ) {
await cancelPaymentLink ( link . id , 'Automatic cleanup of old link' );
}
console . log ( `Cancelled ${ links . data . length } old links` );
};
Inventory Management
// Cancel payment link when product goes out of stock
const handleOutOfStock = async ( productId ) => {
// Find all active payment links for this product
const links = await listPaymentLinks ({ status: 'active' });
const productLinks = links . data . filter ( link =>
link . products . some ( p => p . merchant_product_id === productId )
);
// Cancel each link
for ( const link of productLinks ) {
await cancelPaymentLink ( link . id , 'Product out of stock' );
// Notify customer
await sendEmail ({
to: link . customer . email ,
subject: 'Payment Link Cancelled' ,
body: `Your payment link has been cancelled because the product is out of stock.`
});
}
};
Duplicate Link Prevention
// Cancel previous link when creating a new one for same order
const createReplacementLink = async ( oldLinkId , newAmount ) => {
// Cancel old link
await cancelPaymentLink ( oldLinkId , 'Replaced with updated link' );
// Create new link
const newLink = await createPaymentLink ({
amount_cents: newAmount ,
// ... other params
});
return newLink ;
};
Webhooks
Cancelling a payment link triggers the following webhook event:
{
"type" : "payment_link.cancelled" ,
"data" : {
"id" : "plink_abc123xyz" ,
"status" : "cancelled" ,
"cancelled_at" : "2025-10-18T16:00:00Z" ,
"cancellation_reason" : "Customer requested cancellation"
}
}
See Webhooks Reference for details.
Errors
Status Code Error Code Description 400 invalid_stateLink is not in cancellable state 401 unauthorizedInvalid or missing API key 404 not_foundPayment link not found 429 rate_limit_exceededToo many requests
Cannot Cancel Paid Links
{
"error" : {
"code" : "invalid_state" ,
"message" : "Cannot cancel payment link with status 'paid'" ,
"param" : "status"
}
}
Cannot Cancel Expired Links
{
"error" : {
"code" : "invalid_state" ,
"message" : "Cannot cancel payment link with status 'expired'" ,
"param" : "status"
}
}
Link States and Cancellation
Current Status Can Cancel? Result activeYes Status changes to cancelled paidNo Error: Use refund endpoint instead expiredNo Error: Already expired cancelledNo Error: Already cancelled
Best Practices
Check Status First Verify link is active before attempting to cancel
Provide Reasons Always include a cancellation reason for audit trail
Notify Customers Send email notification when cancelling customer’s link
Handle Webhooks Listen for payment_link.cancelled events
Important Notes
Cannot cancel paid links. If a payment link has already been paid, you must create a Refund instead of cancelling the link.
Cancelled links cannot be reactivated. Once cancelled, a payment link cannot be used again. Create a new link if needed.