Update Payment Link
The Update Payment Link endpoint allows you to modify existing payment links while preserving their core functionality. You can update most configuration settings, product associations, customer experience options, and payment parameters. The system includes comprehensive validation and audit trail logging to track all changes.
Endpoint DetailsCopied!
-
Method:
PUT
-
URL:
/api/v0/payment-links/{id}
-
Content-Type:
application/json
-
Authentication: Required (
x-client-key
andx-client-secret
) -
Scope Required:
payment_link:update
Request HeadersCopied!
Header |
Type |
Required |
Description |
---|---|---|---|
|
string |
Yes |
Your API client key |
|
string |
Yes |
Your API client secret |
|
string |
Yes |
Must be |
Path ParametersCopied!
Parameter |
Type |
Required |
Description |
---|---|---|---|
|
string |
Yes |
The unique UUID of the payment link to update |
Request BodyCopied!
All fields are optional - only include fields you want to update:
Core Fields
Field |
Type |
Description |
Constraints |
---|---|---|---|
|
string |
Display title |
3-100 characters |
|
string |
Detailed description |
Max 500 characters, supports markdown |
|
string |
Cover image URL |
Valid URL format |
|
enum |
Type of payment link |
Cannot be changed after creation |
|
number |
Fixed amount |
Min 0.01, null for product bundles |
Payment Configuration
Field |
Type |
Description |
---|---|---|
|
enum |
Payment currency ( |
|
enum |
Payment frequency |
|
datetime |
Payment link expiration |
|
string |
External reference ID |
|
string |
Specific wallet ID |
Product Configuration
Field |
Type |
Description |
---|---|---|
|
array |
Array of products with quantities |
|
boolean |
Include all products from catalog |
|
boolean |
Allow customers to adjust quantities |
Customer Data Collection
Field |
Type |
Description |
---|---|---|
|
boolean |
Require customer address |
|
boolean |
Require phone number |
|
boolean |
Allow business tax ID input |
|
object |
Custom form fields |
Tax Configuration
Field |
Type |
Description |
---|---|---|
|
boolean |
Apply tax calculation |
|
string |
Tax configuration ID |
Payment Limits & Controls
Field |
Type |
Description |
---|---|---|
|
boolean |
Limit total number of payments |
|
number |
Maximum payment count |
|
string |
Restrict to specific customer |
Payment Methods & Experience
Field |
Type |
Description |
---|---|---|
|
boolean |
Enable mobile payments |
|
boolean |
Enable cryptocurrency payments |
|
enum |
Post-payment page behavior |
|
boolean |
Generate PDF receipts |
Update RestrictionsCopied!
Protected Fields
The following fields cannot be updated after creation:
-
url
- URL slug is permanent -
appId
- Application association is fixed -
linkType
- Payment link type cannot be changed -
createdAt
- Creation timestamp is immutable
Business Logic Constraints
-
Active Payment Links: Some changes may be restricted if the payment link has active transactions
-
Tax Requirements: If
collectTax
is true,taxId
must be provided and valid -
Payment Limits: If
limitPayments
is true,maxPayments
must be specified and greater than 0 -
Product Validation: All products in
paymentLinkProducts
must exist and belong to your app
Example RequestsCopied!
Update Basic Information
curl -X PUT "https://api.devdraft.com/api/v0/payment-links/550e8400-e29b-41d4-a716-446655440000" \
-H "x-client-key: your_client_key" \
-H "x-client-secret: your_client_secret" \
-H "Content-Type: application/json" \
-d '{
"title": "Premium Subscription - Updated",
"description": "Monthly access to all premium features with enhanced support",
"amount": 34.99
}'
Update Product Bundle
curl -X PUT "https://api.devdraft.com/api/v0/payment-links/550e8400-e29b-41d4-a716-446655440001" \
-H "x-client-key: your_client_key" \
-H "x-client-secret: your_client_secret" \
-H "Content-Type: application/json" \
-d '{
"title": "Startup Bundle - Special Offer",
"paymentLinkProducts": [
{
"productId": "123e4567-e89b-12d3-a456-426614174003",
"quantity": 2
},
{
"productId": "123e4567-e89b-12d3-a456-426614174005",
"quantity": 1
}
],
"limitPayments": true,
"maxPayments": 50
}'
Enable Tax Collection
curl -X PUT "https://api.devdraft.com/api/v0/payment-links/550e8400-e29b-41d4-a716-446655440000" \
-H "x-client-key: your_client_key" \
-H "x-client-secret: your_client_secret" \
-H "Content-Type: application/json" \
-d '{
"collectTax": true,
"taxId": "tax_550e8400-e29b-41d4-a716-446655440000",
"collectAddress": true,
"requirePhoneNumber": true
}'
Update Expiration and Payment Methods
curl -X PUT "https://api.devdraft.com/api/v0/payment-links/550e8400-e29b-41d4-a716-446655440000" \
-H "x-client-key: your_client_key" \
-H "x-client-secret: your_client_secret" \
-H "Content-Type: application/json" \
-d '{
"expiration_date": "2025-06-30T23:59:59Z",
"allowMobilePayment": true,
"allowCryptoPayment": false,
"customFields": {
"department": {
"type": "select",
"required": true,
"options": ["Sales", "Marketing", "Engineering", "Support"]
}
}
}'
ResponseCopied!
Success Response (200 OK)
Returns the updated payment link with all current values:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Premium Subscription - Updated",
"description": "Monthly access to all premium features with enhanced support",
"url": "premium-subscription",
"linkType": "PRODUCT",
"status": "ACTIVE",
"amount": 34.99,
"currency": "usdc",
"recurringType": "MONTHLY",
"walletId": "wallet_550e8400-e29b-41d4-a716-446655440000",
"appId": "app_550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2024-01-15T10:30:00Z",
"expiration_date": "2025-06-30T23:59:59Z",
"coverImage": "https://example.com/images/premium-subscription.jpg",
"paymentForId": "sub_premium_2024",
"customerId": null,
"taxId": "tax_550e8400-e29b-41d4-a716-446655440000",
"allowQuantityAdjustment": true,
"collectTax": true,
"collectAddress": true,
"requirePhoneNumber": true,
"limitPayments": false,
"maxPayments": null,
"allowBusinessTaxId": false,
"allowMobilePayment": true,
"allowCryptoPayment": false,
"confirmationPage": "SHOW",
"createInvoicePdf": true,
"isForAllProduct": false,
"customFields": {
"department": {
"type": "select",
"required": true,
"options": ["Sales", "Marketing", "Engineering", "Support"]
}
}
}
Error Responses
404 Not Found - Payment Link Not Found
{
"statusCode": 404,
"message": "Payment link not found",
"error": "Not Found"
}
401 Unauthorized - Access Denied
{
"statusCode": 401,
"message": "Access denied to this payment link",
"error": "Unauthorized"
}
400 Bad Request - Validation Error
{
"statusCode": 400,
"message": [
"Title must be at least 3 characters long",
"Tax with ID 123e4567-e89b-12d3-a456-426655440000 not found"
],
"error": "Bad Request"
}
403 Forbidden - Insufficient Scope
{
"statusCode": 403,
"message": "Insufficient scope for this operation",
"error": "Forbidden"
}
429 Too Many Requests
{
"statusCode": 429,
"message": "Rate limit exceeded",
"error": "Too Many Requests"
}
Integration PatternsCopied!
Partial Updates
async function updatePaymentLinkTitle(paymentLinkId, newTitle) {
try {
const response = await fetch(`/api/v0/payment-links/${paymentLinkId}`, {
method: 'PUT',
headers: {
'x-client-key': 'your_client_key',
'x-client-secret': 'your_client_secret',
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: newTitle
})
});
if (response.ok) {
const updatedPaymentLink = await response.json();
console.log('Payment link updated:', updatedPaymentLink);
return updatedPaymentLink;
} else {
const error = await response.json();
console.error('Update failed:', error);
throw new Error(error.message);
}
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}
Bulk Configuration Update
async function updatePaymentLinkConfiguration(paymentLinkId, config) {
const updateData = {
collectTax: config.enableTax,
collectAddress: config.requireAddress,
requirePhoneNumber: config.requirePhone,
allowMobilePayment: config.enableMobile,
limitPayments: config.hasLimit,
...( config.hasLimit && { maxPayments: config.paymentLimit } ),
...( config.enableTax && { taxId: config.taxConfigId } )
};
try {
const response = await fetch(`/api/v0/payment-links/${paymentLinkId}`, {
method: 'PUT',
headers: {
'x-client-key': 'your_client_key',
'x-client-secret': 'your_client_secret',
'Content-Type': 'application/json'
},
body: JSON.stringify(updateData)
});
if (response.ok) {
return await response.json();
} else {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
} catch (error) {
console.error('Configuration update failed:', error);
throw error;
}
}
// Usage
await updatePaymentLinkConfiguration('payment-link-id', {
enableTax: true,
taxConfigId: 'tax-id',
requireAddress: true,
requirePhone: false,
enableMobile: true,
hasLimit: true,
paymentLimit: 100
});
Product Bundle Management
class PaymentLinkProductManager {
constructor(clientKey, clientSecret) {
this.clientKey = clientKey;
this.clientSecret = clientSecret;
}
async addProduct(paymentLinkId, productId, quantity = 1) {
// First, get current products
const paymentLink = await this.fetchPaymentLink(paymentLinkId);
const currentProducts = paymentLink.paymentLinkProducts || [];
// Add new product
const updatedProducts = [
...currentProducts,
{ productId, quantity }
];
return this.updateProducts(paymentLinkId, updatedProducts);
}
async removeProduct(paymentLinkId, productId) {
const paymentLink = await this.fetchPaymentLink(paymentLinkId);
const updatedProducts = paymentLink.paymentLinkProducts.filter(
p => p.productId !== productId
);
return this.updateProducts(paymentLinkId, updatedProducts);
}
async updateProductQuantity(paymentLinkId, productId, newQuantity) {
const paymentLink = await this.fetchPaymentLink(paymentLinkId);
const updatedProducts = paymentLink.paymentLinkProducts.map(p =>
p.productId === productId ? { ...p, quantity: newQuantity } : p
);
return this.updateProducts(paymentLinkId, updatedProducts);
}
async updateProducts(paymentLinkId, products) {
const response = await fetch(`/api/v0/payment-links/${paymentLinkId}`, {
method: 'PUT',
headers: {
'x-client-key': this.clientKey,
'x-client-secret': this.clientSecret,
'Content-Type': 'application/json'
},
body: JSON.stringify({
paymentLinkProducts: products
})
});
if (!response.ok) {
throw new Error(`Failed to update products: ${response.statusText}`);
}
return response.json();
}
async fetchPaymentLink(paymentLinkId) {
const response = await fetch(`/api/v0/payment-links/${paymentLinkId}`, {
headers: {
'x-client-key': this.clientKey,
'x-client-secret': this.clientSecret
}
});
if (!response.ok) {
throw new Error(`Failed to fetch payment link: ${response.statusText}`);
}
return response.json();
}
}
Validation Before Update
async function validateUpdateData(paymentLinkId, updateData) {
const errors = [];
// Title validation
if (updateData.title !== undefined) {
if (typeof updateData.title !== 'string' || updateData.title.length < 3) {
errors.push('Title must be at least 3 characters long');
}
if (updateData.title.length > 100) {
errors.push('Title cannot exceed 100 characters');
}
}
// Amount validation
if (updateData.amount !== undefined) {
if (typeof updateData.amount !== 'number' || updateData.amount <= 0) {
errors.push('Amount must be a positive number');
}
if (updateData.amount < 0.01) {
errors.push('Amount must be at least 0.01');
}
}
// Tax validation
if (updateData.collectTax === true && !updateData.taxId) {
errors.push('Tax ID is required when tax collection is enabled');
}
// Payment limits validation
if (updateData.limitPayments === true) {
if (!updateData.maxPayments || updateData.maxPayments < 1) {
errors.push('Max payments must be specified and greater than 0 when limiting payments');
}
}
// Product validation
if (updateData.paymentLinkProducts) {
if (!Array.isArray(updateData.paymentLinkProducts)) {
errors.push('Payment link products must be an array');
} else {
updateData.paymentLinkProducts.forEach((product, index) => {
if (!product.productId) {
errors.push(`Product ${index + 1}: Product ID is required`);
}
if (product.quantity && (typeof product.quantity !== 'number' || product.quantity < 1)) {
errors.push(`Product ${index + 1}: Quantity must be a positive number`);
}
});
}
}
return errors;
}
// Usage
const updateData = {
title: 'New Title',
amount: 49.99,
collectTax: true,
taxId: 'tax-id'
};
const validationErrors = await validateUpdateData(paymentLinkId, updateData);
if (validationErrors.length > 0) {
console.error('Validation failed:', validationErrors);
} else {
const updatedPaymentLink = await updatePaymentLink(paymentLinkId, updateData);
}
Business LogicCopied!
Update Behavior
-
Partial Updates: Only fields included in the request body are updated
-
Null Values: Sending
null
for optional fields clears their values -
Empty Strings: Converted to
null
for UUID fields (taxId
,walletId
,customerId
) -
Product Replacement: When updating
paymentLinkProducts
, the entire list is replaced
Audit Trail
All updates are logged with comprehensive audit trails including:
-
User Information: Who made the changes
-
Before/After Values: Complete change tracking
-
Significant Changes: Price changes >5%, status changes, etc.
-
Metadata: Request context and timestamps
Automatic Validation
The system automatically validates:
-
Tax Configuration: Ensures tax exists when
collectTax
is enabled -
Product Existence: Verifies all products in bundles exist
-
Ownership: Confirms payment link belongs to your application
-
Business Rules: Enforces payment limit requirements
Rate LimitingCopied!
-
Limit: 100 requests per minute per API key
-
Headers: Monitor
X-RateLimit-*
headers -
Best Practice: Batch multiple field updates into single requests
Security FeaturesCopied!
-
Ownership Validation: Can only update payment links belonging to your application
-
Field Protection: Prevents updates to immutable fields
-
Scope Enforcement: Requires
payment_link:update
scope -
Input Sanitization: All input data is validated and sanitized
Common Use CasesCopied!
Price Updates
Modify pricing for subscription services or product offerings.
Configuration Changes
Update customer data collection requirements or payment method availability.
Product Bundle Management
Add, remove, or modify products in bundle payment links.
Seasonal Adjustments
Set expiration dates for promotional campaigns or limited-time offers.
Experience Optimization
Update descriptions, images, and custom fields based on customer feedback.