Fetch a Checkout Form
Retrieve a Checkout Form by its ID to check its status, get the payment link, or view submitted buyer information.
Overview
Use this endpoint to:
- Get the checkout URL to send to customers
- Check form status (active, expired, completed)
- Retrieve buyer details after form submission
- Verify configuration before sending to customers
- Monitor form usage and expiration
Use Cases
1. Get Checkout URL for Customer
Retrieve the link to send to your customer:
async function getCheckoutUrl(checkoutFormId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/checkout_forms/${checkoutFormId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
console.log('Checkout URL:', form.link_url);
console.log('Expires:', new Date(form.link_expires_at));
console.log('State:', form.state);
return form.link_url;
}
2. Check Form Status
Verify if form is still active:
async function isCheckoutFormActive(checkoutFormId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/checkout_forms/${checkoutFormId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
const now = new Date();
const expiresAt = new Date(form.link_expires_at);
const isActive = form.state === 'ACTIVE' && expiresAt > now;
console.log('Form Status:', {
state: form.state,
expires_at: form.link_expires_at,
is_expired: expiresAt <= now,
is_active: isActive
});
return isActive;
}
3. Retrieve Buyer Information
Get buyer details after form submission:
async function getBuyerDetails(checkoutFormId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/checkout_forms/${checkoutFormId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
if (form.buyer_details) {
console.log('Buyer Information:');
console.log('Name:', form.buyer_details.name);
console.log('Email:', form.buyer_details.email);
console.log('Phone:', form.buyer_details.phone_number);
if (form.buyer_details.billing_address) {
console.log('Billing Address:', {
street: form.buyer_details.billing_address.street,
city: form.buyer_details.billing_address.city,
state: form.buyer_details.billing_address.region,
postal_code: form.buyer_details.billing_address.postal_code,
country: form.buyer_details.billing_address.country
});
}
if (form.buyer_details.shipping_address) {
console.log('Shipping Address:', {
street: form.buyer_details.shipping_address.street,
city: form.buyer_details.shipping_address.city,
state: form.buyer_details.shipping_address.region,
postal_code: form.buyer_details.shipping_address.postal_code,
country: form.buyer_details.shipping_address.country
});
}
return form.buyer_details;
}
console.log('No buyer details yet (form not submitted)');
return null;
}
4. Verify Form Configuration
Check form settings before sending to customer:
async function verifyCheckoutForm(checkoutFormId, expectedConfig) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/checkout_forms/${checkoutFormId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
// Verify key settings
const verification = {
merchant_id: form.merchant_id === expectedConfig.merchantId,
payment_frequency: form.payment_frequency === expectedConfig.paymentFrequency,
total_amount: form.amount_details?.total_amount === expectedConfig.totalAmount,
allowed_methods: JSON.stringify(form.allowed_payment_methods) === JSON.stringify(expectedConfig.allowedMethods),
has_branding: !!form.branding,
has_items: form.items?.length > 0
};
const isValid = Object.values(verification).every(v => v);
console.log('Form Verification:', {
form_id: form.id,
is_valid: isValid,
checks: verification
});
if (!isValid) {
console.error('Configuration mismatch detected!');
}
return isValid;
}
5. Monitor Form Expiration
Check time remaining before expiration:
async function getFormTimeRemaining(checkoutFormId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/checkout_forms/${checkoutFormId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
const now = new Date();
const expiresAt = new Date(form.link_expires_at);
const msRemaining = expiresAt - now;
if (msRemaining <= 0) {
console.log('Form has expired');
return {
expired: true,
time_remaining: 0
};
}
const minutesRemaining = Math.floor(msRemaining / 60000);
const hoursRemaining = Math.floor(minutesRemaining / 60);
const daysRemaining = Math.floor(hoursRemaining / 24);
console.log('Time Remaining:', {
days: daysRemaining,
hours: hoursRemaining % 24,
minutes: minutesRemaining % 60,
expires_at: form.link_expires_at
});
return {
expired: false,
time_remaining: msRemaining,
days: daysRemaining,
hours: hoursRemaining,
minutes: minutesRemaining
};
}
6. Resend Checkout Link
Retrieve link to resend to customer:
async function resendCheckoutLink(checkoutFormId, customerEmail) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/checkout_forms/${checkoutFormId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
// Check if form is still valid
const expiresAt = new Date(form.link_expires_at);
if (expiresAt <= new Date()) {
console.error('Cannot resend: checkout form has expired');
throw new Error('Checkout form expired. Please create a new one.');
}
if (form.state !== 'ACTIVE') {
console.error('Cannot resend: checkout form is not active');
throw new Error('Checkout form is not active');
}
// Resend email
await sendEmail(customerEmail, {
subject: 'Your Payment Link (Resent)',
template: 'checkout_reminder',
data: {
checkout_url: form.link_url,
expires_at: form.link_expires_at,
amount: form.amount_details?.total_amount
}
});
console.log('Checkout link resent to:', customerEmail);
return form;
}
7. Form Details for Dashboard
Display form information in admin dashboard:
async function getFormDetailsForDashboard(checkoutFormId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/checkout_forms/${checkoutFormId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
return {
id: form.id,
created: new Date(form.created_at).toLocaleDateString(),
nickname: form.nickname || 'Unnamed Form',
amount: form.amount_details?.total_amount
? `$${(form.amount_details.total_amount / 100).toFixed(2)}`
: 'Variable',
payment_type: form.payment_frequency,
state: form.state,
expires: new Date(form.link_expires_at).toLocaleDateString(),
link: form.link_url,
buyer_name: form.buyer_details?.name || 'Not submitted',
buyer_email: form.buyer_details?.email || 'Not submitted',
items_count: form.items?.length || 0,
tags: form.tags
};
}
8. Integration with Order Management
Sync checkout form with order status:
async function syncOrderWithCheckoutForm(orderId) {
// Get order from database
const order = await db.orders.findById(orderId);
if (!order.checkout_form_id) {
console.log('No checkout form associated with order');
return;
}
// Fetch checkout form
const response = await fetch(
`https://api.ahrvo.network/payments/na/checkout_forms/${order.checkout_form_id}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
// Update order with buyer details if available
if (form.buyer_details) {
await db.orders.update(orderId, {
customer_name: form.buyer_details.name,
customer_email: form.buyer_details.email,
customer_phone: form.buyer_details.phone_number,
billing_address: form.buyer_details.billing_address,
shipping_address: form.buyer_details.shipping_address,
checkout_completed: true
});
console.log('Order updated with buyer details');
}
// Check if form expired
if (new Date(form.link_expires_at) <= new Date() && order.status === 'PENDING_PAYMENT') {
await db.orders.update(orderId, {
status: 'CHECKOUT_EXPIRED'
});
console.log('Order marked as checkout expired');
}
return form;
}
Response Fields
Core Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique checkout form ID |
created_at | string | Creation timestamp |
updated_at | string | Last update timestamp |
merchant_id | string | Associated merchant |
application_id | string | Associated application |
state | string | Form state (e.g., ACTIVE) |
Link Details
| Field | Type | Description |
|---|---|---|
link_url | string | The checkout URL for customers |
link_expires_at | string | When the link expires |
Configuration
| Field | Type | Description |
|---|---|---|
payment_frequency | string | ONE_TIME or RECURRING |
is_multiple_use | boolean | Whether form can be reused |
allowed_payment_methods | array | Allowed payment methods |
nickname | string | Form nickname |
Buyer Details (After Submission)
| Field | Type | Description |
|---|---|---|
buyer_details.name | string | Buyer's name |
buyer_details.email | string | Buyer's email |
buyer_details.phone_number | string | Buyer's phone |
buyer_details.billing_address | object | Billing address |
buyer_details.shipping_address | object | Shipping address |
Items and Pricing
| Field | Type | Description |
|---|---|---|
items | array | Products/services |
amount_details | object | Pricing information |
amount_details.total_amount | integer | Total amount in cents |
amount_details.amount_type | string | FIXED or VARIABLE |
Best Practices
1. Cache Form Data
Cache checkout form details to reduce API calls:
const formCache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
async function getCachedCheckoutForm(checkoutFormId) {
const cached = formCache.get(checkoutFormId);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
console.log('Returning cached form data');
return cached.data;
}
const response = await fetch(
`https://api.ahrvo.network/payments/na/checkout_forms/${checkoutFormId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
formCache.set(checkoutFormId, {
data: form,
timestamp: Date.now()
});
return form;
}
2. Handle Expired Forms
Always check expiration before using:
async function ensureFormIsValid(checkoutFormId) {
const form = await getCachedCheckoutForm(checkoutFormId);
if (new Date(form.link_expires_at) <= new Date()) {
throw new Error('Checkout form has expired. Please create a new one.');
}
if (form.state !== 'ACTIVE') {
throw new Error(`Checkout form is ${form.state}. Cannot use.`);
}
return form;
}
3. Store Buyer Details
Save buyer information from completed forms:
async function processBuyerDetails(checkoutFormId) {
const form = await getCachedCheckoutForm(checkoutFormId);
if (!form.buyer_details) {
console.log('No buyer details available yet');
return null;
}
// Store in your database
const customer = await db.customers.upsert({
email: form.buyer_details.email,
name: form.buyer_details.name,
phone: form.buyer_details.phone_number,
billing_address: form.buyer_details.billing_address,
shipping_address: form.buyer_details.shipping_address
});
console.log('Customer record updated:', customer.id);
return customer;
}
4. Monitor Form Usage
Track when forms are viewed:
async function trackCheckoutFormAccess(checkoutFormId, source) {
const form = await getCachedCheckoutForm(checkoutFormId);
await db.analytics.create({
event: 'checkout_form_accessed',
checkout_form_id: checkoutFormId,
source: source,
timestamp: new Date(),
form_state: form.state,
expires_at: form.link_expires_at
});
}
5. Error Handling
Handle errors gracefully:
async function safeGetCheckoutForm(checkoutFormId) {
try {
const response = await fetch(
`https://api.ahrvo.network/payments/na/checkout_forms/${checkoutFormId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
if (response.status === 404) {
throw new Error('Checkout form not found');
}
if (!response.ok) {
const error = await response.json();
throw new Error(`API error: ${error._embedded?.errors?.[0]?.message || 'Unknown error'}`);
}
return await response.json();
} catch (error) {
console.error('Error fetching checkout form:', error);
throw error;
}
}
Common Workflows
Email Reminder Workflow
async function sendExpirationReminder(checkoutFormId, customerEmail) {
const form = await getCachedCheckoutForm(checkoutFormId);
const expiresAt = new Date(form.link_expires_at);
const hoursRemaining = (expiresAt - new Date()) / (1000 * 60 * 60);
if (hoursRemaining > 0 && hoursRemaining < 24) {
await sendEmail(customerEmail, {
subject: 'Your checkout link expires soon!',
template: 'checkout_expiring',
data: {
checkout_url: form.link_url,
hours_remaining: Math.round(hoursRemaining),
amount: form.amount_details?.total_amount
}
});
console.log('Expiration reminder sent');
}
}
Webhook Integration
// When receiving payment success webhook
async function handlePaymentSuccess(webhookData) {
const checkoutFormId = webhookData.checkout_form_id;
// Fetch form to get buyer details
const form = await getCachedCheckoutForm(checkoutFormId);
if (form.buyer_details) {
// Update order with complete information
await db.orders.update(webhookData.order_id, {
status: 'PAID',
customer_name: form.buyer_details.name,
customer_email: form.buyer_details.email,
billing_address: form.buyer_details.billing_address,
shipping_address: form.buyer_details.shipping_address
});
// Send confirmation email
await sendEmail(form.buyer_details.email, {
subject: 'Payment Confirmed',
template: 'order_confirmation',
data: {
order_id: webhookData.order_id,
items: form.items
}
});
}
}