Fetch Payment Link
The Fetch Payment Link endpoint retrieves detailed information about a specific payment link using its unique identifier. This endpoint provides complete payment link data including configuration settings, product associations, payment options, and current status.
Endpoint DetailsCopied!
-
Method:
GET
-
URL:
/api/v0/payment-links/{id}
-
Content-Type:
application/json
-
Authentication: Required (
x-client-key
andx-client-secret
) -
Scope Required:
payment_link:read
Request HeadersCopied!
Header |
Type |
Required |
Description |
---|---|---|---|
|
string |
Yes |
Your API client key |
|
string |
Yes |
Your API client secret |
Path ParametersCopied!
Parameter |
Type |
Required |
Description |
---|---|---|---|
|
string |
Yes |
The unique UUID of the payment link to retrieve |
ResponseCopied!
Success Response (200 OK)
Returns a complete payment link object with all configuration details:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Premium Subscription",
"description": "Monthly access to all premium features with priority support",
"url": "premium-subscription",
"linkType": "PRODUCT",
"status": "ACTIVE",
"amount": 29.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": "2024-12-31T23: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": true,
"maxPayments": 1000,
"allowBusinessTaxId": false,
"allowMobilePayment": true,
"allowCryptoPayment": true,
"confirmationPage": "SHOW",
"createInvoicePdf": true,
"isForAllProduct": false,
"customFields": {
"company_size": {
"type": "select",
"required": true,
"options": ["1-10", "11-50", "51-200", "200+"]
},
"use_case": {
"type": "textarea",
"required": false,
"placeholder": "How will you use our service?"
}
}
}
Product Bundle Payment Link Response
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"title": "Startup Bundle",
"description": "Everything you need to get started",
"url": "startup-bundle",
"linkType": "PRODUCT",
"status": "ACTIVE",
"amount": null,
"currency": "usdc",
"recurringType": "ONE_TIME",
"walletId": "wallet_550e8400-e29b-41d4-a716-446655440000",
"appId": "app_550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2024-01-10T08:15:00Z",
"expiration_date": null,
"coverImage": null,
"paymentForId": "bundle_startup_2024",
"customerId": null,
"taxId": "tax_550e8400-e29b-41d4-a716-446655440000",
"allowQuantityAdjustment": true,
"collectTax": true,
"collectAddress": true,
"requirePhoneNumber": false,
"limitPayments": false,
"maxPayments": null,
"allowBusinessTaxId": true,
"allowMobilePayment": false,
"allowCryptoPayment": true,
"confirmationPage": "SHOW",
"createInvoicePdf": false,
"isForAllProduct": false,
"customFields": null,
"paymentLinkProducts": [
{
"productId": "123e4567-e89b-12d3-a456-426614174003",
"quantity": 1
},
{
"productId": "123e4567-e89b-12d3-a456-426614174004",
"quantity": 2
}
]
}
Error Responses
404 Not Found - Payment Link Not Found
{
"statusCode": 404,
"message": "Payment link not found",
"error": "Not Found"
}
401 Unauthorized - Invalid Authentication
{
"statusCode": 401,
"message": "Application not authenticated",
"error": "Unauthorized"
}
401 Unauthorized - Access Denied
{
"statusCode": 401,
"message": "Access denied to this payment link",
"error": "Unauthorized"
}
403 Forbidden - Insufficient Scope
{
"statusCode": 403,
"message": "Insufficient scope for this operation",
"error": "Forbidden"
}
400 Bad Request - Invalid UUID Format
{
"statusCode": 400,
"message": "Invalid UUID format",
"error": "Bad Request"
}
429 Too Many Requests
{
"statusCode": 429,
"message": "Rate limit exceeded",
"error": "Too Many Requests"
}
Example RequestsCopied!
Basic Payment Link Fetch
curl -X GET "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"
JavaScript/TypeScript Example
async function fetchPaymentLink(paymentLinkId) {
try {
const response = await fetch(`/api/v0/payment-links/${paymentLinkId}`, {
method: 'GET',
headers: {
'x-client-key': 'your_client_key',
'x-client-secret': 'your_client_secret'
}
});
if (response.ok) {
const paymentLink = await response.json();
console.log('Payment link retrieved:', paymentLink);
return paymentLink;
} else if (response.status === 404) {
console.log('Payment link not found');
return null;
} else if (response.status === 401) {
console.log('Access denied or authentication failed');
throw new Error('Unauthorized access');
} else {
console.error('Failed to fetch payment link:', response.statusText);
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}
// Usage
const paymentLink = await fetchPaymentLink('550e8400-e29b-41d4-a716-446655440000');
Python Example
import requests
def fetch_payment_link(payment_link_id, client_key, client_secret):
"""Fetch a payment link by ID from the Devdraft API"""
url = f"https://api.devdraft.com/api/v0/payment-links/{payment_link_id}"
headers = {
'x-client-key': client_key,
'x-client-secret': client_secret
}
try:
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
elif response.status_code == 404:
print(f"Payment link {payment_link_id} not found")
return None
elif response.status_code == 401:
print("Access denied or authentication failed")
raise ValueError("Unauthorized access")
else:
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Error fetching payment link: {e}")
raise
# Usage
payment_link = fetch_payment_link(
'550e8400-e29b-41d4-a716-446655440000',
'your_client_key',
'your_client_secret'
)
Response FieldsCopied!
Core Information
Field |
Type |
Description |
---|---|---|
|
string |
Unique payment link identifier (UUID) |
|
string |
Display title of the payment link |
|
string |
Detailed description (nullable) |
|
string |
URL slug for accessing the payment link |
|
enum |
Current status ( |
|
datetime |
Payment link creation timestamp |
Payment Configuration
Field |
Type |
Description |
---|---|---|
|
enum |
Type of payment link ( |
|
number |
Fixed amount (nullable for product bundles) |
|
enum |
Payment currency ( |
|
enum |
Payment frequency ( |
|
datetime |
Link expiration date (nullable) |
Associated Resources
Field |
Type |
Description |
---|---|---|
|
string |
Associated wallet identifier |
|
string |
Your application identifier |
|
string |
Specific customer restriction (nullable) |
|
string |
Tax configuration ID (nullable) |
|
string |
External reference identifier (nullable) |
|
string |
Cover image URL (nullable) |
Customer Experience Settings
Field |
Type |
Description |
---|---|---|
|
boolean |
Can customers adjust product quantities |
|
boolean |
Tax collection enabled |
|
boolean |
Customer address collection required |
|
boolean |
Phone number collection required |
|
boolean |
Business tax ID collection enabled |
|
boolean |
Mobile payment options available |
|
boolean |
Cryptocurrency payments enabled |
Advanced Configuration
Field |
Type |
Description |
---|---|---|
|
boolean |
Payment count is limited |
|
number |
Maximum number of payments allowed (nullable) |
|
boolean |
Includes all products from catalog |
|
enum |
Post-payment page behavior ( |
|
boolean |
Generate PDF receipts |
|
object |
Custom form fields configuration (nullable) |
Product Association
Field |
Type |
Description |
---|---|---|
|
array |
Associated products with quantities (for bundles) |
|
string |
Product UUID |
|
number |
Product quantity |
Integration PatternsCopied!
Payment Link Details Display
function PaymentLinkDetails({ paymentLinkId }) {
const [paymentLink, setPaymentLink] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function loadPaymentLink() {
try {
setLoading(true);
const data = await fetchPaymentLink(paymentLinkId);
setPaymentLink(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
if (paymentLinkId) {
loadPaymentLink();
}
}, [paymentLinkId]);
if (loading) return <div>Loading payment link...</div>;
if (error) return <div>Error: {error}</div>;
if (!paymentLink) return <div>Payment link not found</div>;
const isExpired = paymentLink.expiration_date &&
new Date(paymentLink.expiration_date) < new Date();
return (
<div className="payment-link-details">
<div className="header">
<h2>{paymentLink.title}</h2>
<span className={`status ${paymentLink.status.toLowerCase()}`}>
{paymentLink.status}
</span>
{isExpired && <span className="expired">EXPIRED</span>}
</div>
{paymentLink.coverImage && (
<img
src={paymentLink.coverImage}
alt={paymentLink.title}
className="cover-image"
/>
)}
<div className="description">
<p>{paymentLink.description}</p>
</div>
<div className="payment-info">
<div className="amount">
{paymentLink.amount ? (
<span>${paymentLink.amount} {paymentLink.currency.toUpperCase()}</span>
) : (
<span>Variable Amount</span>
)}
</div>
<div className="frequency">
{paymentLink.recurringType !== 'ONE_TIME' && (
<span>Recurring: {paymentLink.recurringType}</span>
)}
</div>
</div>
<div className="configuration">
<h3>Configuration</h3>
<ul>
<li>Type: {paymentLink.linkType}</li>
<li>Tax Collection: {paymentLink.collectTax ? 'Enabled' : 'Disabled'}</li>
<li>Address Required: {paymentLink.collectAddress ? 'Yes' : 'No'}</li>
<li>Phone Required: {paymentLink.requirePhoneNumber ? 'Yes' : 'No'}</li>
{paymentLink.limitPayments && (
<li>Payment Limit: {paymentLink.maxPayments}</li>
)}
</ul>
</div>
{paymentLink.paymentLinkProducts && (
<div className="products">
<h3>Products ({paymentLink.paymentLinkProducts.length})</h3>
<ul>
{paymentLink.paymentLinkProducts.map((product, index) => (
<li key={index}>
Product ID: {product.productId} (Qty: {product.quantity})
</li>
))}
</ul>
</div>
)}
<div className="payment-methods">
<h3>Accepted Payment Methods</h3>
<ul>
{paymentLink.allowCryptoPayment && <li>Cryptocurrency</li>}
{paymentLink.allowMobilePayment && <li>Mobile Payment</li>}
<li>Credit/Debit Card</li>
</ul>
</div>
<div className="meta">
<p><strong>Created:</strong> {new Date(paymentLink.createdAt).toLocaleDateString()}</p>
{paymentLink.expiration_date && (
<p><strong>Expires:</strong> {new Date(paymentLink.expiration_date).toLocaleDateString()}</p>
)}
<p><strong>URL:</strong> <code>{paymentLink.url}</code></p>
</div>
</div>
);
}
Payment Link Validation
async function validatePaymentLink(paymentLinkId) {
try {
const paymentLink = await fetchPaymentLink(paymentLinkId);
if (!paymentLink) {
return { valid: false, reason: 'Payment link not found' };
}
if (paymentLink.status !== 'ACTIVE') {
return { valid: false, reason: 'Payment link is not active' };
}
const now = new Date();
if (paymentLink.expiration_date && new Date(paymentLink.expiration_date) < now) {
return { valid: false, reason: 'Payment link has expired' };
}
if (paymentLink.limitPayments && paymentLink.maxPayments <= 0) {
return { valid: false, reason: 'Payment limit reached' };
}
return {
valid: true,
paymentLink: paymentLink,
requiresAddress: paymentLink.collectAddress,
requiresPhone: paymentLink.requirePhoneNumber,
allowsQuantityAdjustment: paymentLink.allowQuantityAdjustment
};
} catch (error) {
return {
valid: false,
reason: 'Failed to validate payment link',
error: error.message
};
}
}
// Usage in checkout flow
async function initializeCheckout(paymentLinkId) {
const validation = await validatePaymentLink(paymentLinkId);
if (!validation.valid) {
throw new Error(`Cannot proceed with checkout: ${validation.reason}`);
}
// Configure checkout form based on payment link settings
const checkoutConfig = {
paymentLink: validation.paymentLink,
formFields: {
address: validation.requiresAddress,
phone: validation.requiresPhone
},
features: {
quantityAdjustment: validation.allowsQuantityAdjustment,
customFields: validation.paymentLink.customFields
}
};
return checkoutConfig;
}
Cache Management
class PaymentLinkCache {
constructor() {
this.cache = new Map();
this.cacheTimeout = 10 * 60 * 1000; // 10 minutes
}
async getPaymentLink(id) {
const cached = this.cache.get(id);
if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
return cached.data;
}
const paymentLink = await fetchPaymentLink(id);
if (paymentLink) {
this.cache.set(id, {
data: paymentLink,
timestamp: Date.now()
});
}
return paymentLink;
}
invalidate(id) {
this.cache.delete(id);
}
clear() {
this.cache.clear();
}
}
const paymentLinkCache = new PaymentLinkCache();
// Usage
const paymentLink = await paymentLinkCache.getPaymentLink(paymentLinkId);
Security FeaturesCopied!
-
App Isolation: Can only access payment links belonging to your application
-
Access Control: Validates ownership before returning data
-
Scope Validation: Requires
payment_link:read
scope -
Authentication Required: All requests must include valid API credentials
Rate LimitingCopied!
-
Limit: 100 requests per minute per API key
-
Headers: Monitor
X-RateLimit-*
headers in responses -
Best Practice: Implement caching to reduce API calls
Common Use CasesCopied!
Checkout Integration
Retrieve payment link details to configure checkout forms and validation rules.
Payment Link Management
Display payment link information in admin dashboards for monitoring and management.
Validation Before Processing
Verify payment link status and configuration before processing payments.
Analytics and Reporting
Fetch payment link data for usage analysis and performance reporting.
Dynamic Form Generation
Use payment link configuration to dynamically generate appropriate checkout forms.