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.