List Compliance Forms
Retrieve a paginated list of Compliance Forms to monitor merchant compliance status, track form completion, and manage PCI DSS requirements across your platform.
Overview
Use this endpoint to:
- Monitor platform-wide compliance status
- Find incomplete forms requiring merchant action
- Track expired forms needing renewal
- Filter by merchant to check specific merchant compliance
- Generate compliance reports and analytics
- Identify overdue forms approaching due dates
Use Cases
1. List All Compliance Forms
Get a paginated list of all compliance forms:
async function listAllComplianceForms(limit = 20) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms?limit=${limit}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const data = await response.json();
console.log(`Found ${data._embedded?.compliance_forms?.length || 0} forms`);
console.log('Has more:', data.has_more);
data._embedded?.compliance_forms?.forEach(form => {
console.log({
id: form.id,
merchant: form.linked_to,
type: form.type,
state: form.state,
due: new Date(form.due_at).toLocaleDateString(),
valid_until: new Date(form.valid_until).toLocaleDateString()
});
});
return data;
}
2. Find Incomplete Forms
Get all forms that need merchant completion:
async function findIncompleteForms() {
const response = await fetch(
'https://api.ahrvo.network/payments/na/compliance_forms?state=INCOMPLETE&limit=100',
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const data = await response.json();
const incompleteForms = data._embedded?.compliance_forms || [];
console.log(`Found ${incompleteForms.length} incomplete forms`);
// Sort by due date
const sortedForms = incompleteForms.sort((a, b) =>
new Date(a.due_at) - new Date(b.due_at)
);
// Identify overdue forms
const now = new Date();
const overdue = sortedForms.filter(form => new Date(form.due_at) < now);
const upcoming = sortedForms.filter(form => new Date(form.due_at) >= now);
console.log('Overdue forms:', overdue.length);
console.log('Upcoming due forms:', upcoming.length);
return {
all: incompleteForms,
overdue,
upcoming
};
}
3. Get Forms by Merchant
Retrieve all compliance forms for a specific merchant:
async function getMerchantForms(merchantId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms?linked_to=${merchantId}&limit=100`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const data = await response.json();
const forms = data._embedded?.compliance_forms || [];
const summary = {
merchant_id: merchantId,
total: forms.length,
by_state: {
INCOMPLETE: forms.filter(f => f.state === 'INCOMPLETE').length,
COMPLETE: forms.filter(f => f.state === 'COMPLETE').length,
EXPIRED: forms.filter(f => f.state === 'EXPIRED').length
},
by_type: {},
forms: forms
};
// Count by type
forms.forEach(form => {
summary.by_type[form.type] = (summary.by_type[form.type] || 0) + 1;
});
console.log('Merchant Compliance Summary:', summary);
return summary;
}
4. Find Expiring Forms
Identify forms expiring within a threshold:
async function findExpiringForms(daysThreshold = 30) {
const response = await fetch(
'https://api.ahrvo.network/payments/na/compliance_forms?state=COMPLETE&limit=100',
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const data = await response.json();
const completeForms = data._embedded?.compliance_forms || [];
const now = new Date();
const thresholdDate = new Date(now.getTime() + (daysThreshold * 24 * 60 * 60 * 1000));
const expiringForms = completeForms.filter(form => {
const validUntil = new Date(form.valid_until);
return validUntil > now && validUntil <= thresholdDate;
});
console.log(`Found ${expiringForms.length} forms expiring within ${daysThreshold} days`);
expiringForms.forEach(form => {
const validUntil = new Date(form.valid_until);
const daysRemaining = Math.ceil((validUntil - now) / (1000 * 60 * 60 * 24));
console.log({
id: form.id,
merchant: form.linked_to,
type: form.type,
days_remaining: daysRemaining,
valid_until: form.valid_until
});
});
return expiringForms;
}
5. Filter by State
Get forms in a specific state:
async function getFormsByState(state) {
// state can be: INCOMPLETE, COMPLETE, or EXPIRED
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms?state=${state}&limit=100`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const data = await response.json();
const forms = data._embedded?.compliance_forms || [];
console.log(`Found ${forms.length} ${state} forms`);
return forms;
}
// Examples
const incompleteForms = await getFormsByState('INCOMPLETE');
const completedForms = await getFormsByState('COMPLETE');
const expiredForms = await getFormsByState('EXPIRED');
6. Generate Compliance Dashboard
Create comprehensive compliance analytics:
async function generateComplianceDashboard() {
// Fetch all forms (may need pagination for large datasets)
let allForms = [];
let cursor = null;
do {
const url = cursor
? `https://api.ahrvo.network/payments/na/compliance_forms?after_cursor=${cursor}&limit=100`
: 'https://api.ahrvo.network/payments/na/compliance_forms?limit=100';
const response = await fetch(url, {
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
});
const data = await response.json();
const forms = data._embedded?.compliance_forms || [];
allForms.push(...forms);
cursor = data.has_more ? data._links?.next?.href?.split('after_cursor=')[1]?.split('&')[0] : null;
} while (cursor);
// Generate analytics
const dashboard = {
total_forms: allForms.length,
by_state: {
INCOMPLETE: 0,
COMPLETE: 0,
EXPIRED: 0
},
by_type: {},
unique_merchants: new Set(),
overdue: 0,
expiring_soon: 0, // within 30 days
compliance_rate: 0
};
const now = new Date();
const thirtyDaysFromNow = new Date(now.getTime() + (30 * 24 * 60 * 60 * 1000));
allForms.forEach(form => {
// Count by state
dashboard.by_state[form.state]++;
// Count by type
dashboard.by_type[form.type] = (dashboard.by_type[form.type] || 0) + 1;
// Track merchants
dashboard.unique_merchants.add(form.linked_to);
// Count overdue
if (form.state === 'INCOMPLETE' && new Date(form.due_at) < now) {
dashboard.overdue++;
}
// Count expiring soon
if (form.state === 'COMPLETE') {
const validUntil = new Date(form.valid_until);
if (validUntil > now && validUntil <= thirtyDaysFromNow) {
dashboard.expiring_soon++;
}
}
});
// Calculate compliance rate
dashboard.compliance_rate = allForms.length > 0
? ((dashboard.by_state.COMPLETE / allForms.length) * 100).toFixed(2)
: 0;
dashboard.unique_merchants = dashboard.unique_merchants.size;
console.log('Compliance Dashboard:', dashboard);
return dashboard;
}
7. Export Forms to CSV
Export compliance forms for reporting:
async function exportComplianceFormsCSV(filters = {}) {
// Build query string
const params = new URLSearchParams();
if (filters.state) params.append('state', filters.state);
if (filters.linked_to) params.append('linked_to', filters.linked_to);
params.append('limit', '100');
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms?${params}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const data = await response.json();
const forms = data._embedded?.compliance_forms || [];
// Build CSV
const headers = [
'Form ID',
'Merchant ID',
'Type',
'State',
'Created At',
'Due Date',
'Valid From',
'Valid Until',
'Signer Name',
'Signed At',
'Unsigned File',
'Signed File'
];
const rows = forms.map(form => [
form.id,
form.linked_to,
form.type,
form.state,
new Date(form.created_at).toLocaleDateString(),
new Date(form.due_at).toLocaleDateString(),
new Date(form.valid_from).toLocaleDateString(),
new Date(form.valid_until).toLocaleDateString(),
form.pci_saq_a?.name || '',
form.pci_saq_a?.signed_at ? new Date(form.pci_saq_a.signed_at).toLocaleDateString() : '',
form.unsigned_file || '',
form.signed_file || ''
]);
const csv = [
headers.join(','),
...rows.map(row => row.map(cell => `"${cell}"`).join(','))
].join('\n');
console.log(`Exported ${forms.length} forms to CSV`);
return csv;
}
8. Send Compliance Reminders
Notify merchants with incomplete or expiring forms:
async function sendComplianceReminders() {
// Find incomplete forms
const incomplete = await findIncompleteForms();
// Send reminders for overdue forms
for (const form of incomplete.overdue) {
await sendEmail(await getMerchantEmail(form.linked_to), {
subject: 'URGENT: Overdue Compliance Form',
template: 'compliance_overdue',
data: {
form_type: form.type,
due_date: form.due_at,
days_overdue: Math.floor((new Date() - new Date(form.due_at)) / (1000 * 60 * 60 * 24)),
unsigned_file: form.unsigned_file
}
});
console.log(`Sent overdue reminder to merchant ${form.linked_to}`);
}
// Send reminders for upcoming due forms
for (const form of incomplete.upcoming) {
const daysUntilDue = Math.ceil((new Date(form.due_at) - new Date()) / (1000 * 60 * 60 * 24));
if (daysUntilDue <= 7) { // Within 7 days
await sendEmail(await getMerchantEmail(form.linked_to), {
subject: 'Compliance Form Due Soon',
template: 'compliance_reminder',
data: {
form_type: form.type,
due_date: form.due_at,
days_until_due: daysUntilDue,
unsigned_file: form.unsigned_file
}
});
console.log(`Sent upcoming reminder to merchant ${form.linked_to}`);
}
}
// Send renewal reminders for expiring forms
const expiring = await findExpiringForms(30);
for (const form of expiring) {
await sendEmail(await getMerchantEmail(form.linked_to), {
subject: 'Compliance Form Expiring Soon',
template: 'compliance_expiring',
data: {
form_type: form.type,
valid_until: form.valid_until,
days_remaining: Math.ceil((new Date(form.valid_until) - new Date()) / (1000 * 60 * 60 * 24))
}
});
console.log(`Sent expiration reminder to merchant ${form.linked_to}`);
}
}
Query Parameters
| Parameter | Type | Description |
|---|---|---|
limit | integer | Number of results per page (default: 20, max: 100) |
after_cursor | string | Cursor for forward pagination |
before_cursor | string | Cursor for backward pagination |
state | string | Filter by state: INCOMPLETE, COMPLETE, or EXPIRED |
linked_to | string | Filter by merchant ID |
Response Fields
| Field | Type | Description |
|---|---|---|
_embedded.compliance_forms | array | Array of compliance form objects |
has_more | boolean | Whether more results exist |
_links.next | object | Link to next page (if has_more is true) |
_links.prev | object | Link to previous page |
Compliance Form Object
Each form in the array contains:
id- Form IDcreated_at- Creation timestampstate- INCOMPLETE, COMPLETE, or EXPIREDtype- Form type (e.g., PCI_SAQ_A)linked_to- Merchant IDlinked_type- Entity typedue_at- Due datevalid_from- Validity start datevalid_until- Validity end dateunsigned_file- URL to unsigned formsigned_file- URL to signed form (if complete)pci_saq_a- Signature details (if complete)
Best Practices
1. Use Filters to Reduce Data
Filter results to get only what you need:
// Good: Filter by state
const incompleteForms = await fetch(
'https://api.ahrvo.network/payments/na/compliance_forms?state=INCOMPLETE',
{ /* ... */ }
);
// Avoid: Fetching all and filtering client-side
// Only do this if you need all data for analytics
2. Paginate Large Result Sets
Use cursor pagination for large datasets:
async function getAllComplianceForms() {
const allForms = [];
let cursor = null;
do {
const url = cursor
? `https://api.ahrvo.network/payments/na/compliance_forms?after_cursor=${cursor}&limit=100`
: 'https://api.ahrvo.network/payments/na/compliance_forms?limit=100';
const response = await fetch(url, {
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
});
const data = await response.json();
allForms.push(...(data._embedded?.compliance_forms || []));
cursor = data.has_more ? data._links?.next?.href?.split('after_cursor=')[1]?.split('&')[0] : null;
} while (cursor);
return allForms;
}
3. Cache List Results
Cache to reduce API calls:
const listCache = {
data: null,
timestamp: 0,
ttl: 5 * 60 * 1000 // 5 minutes
};
async function getCachedComplianceList(filters = {}) {
const cacheKey = JSON.stringify(filters);
if (listCache.key === cacheKey &&
Date.now() - listCache.timestamp < listCache.ttl) {
return listCache.data;
}
const params = new URLSearchParams(filters);
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms?${params}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const data = await response.json();
listCache.data = data;
listCache.key = cacheKey;
listCache.timestamp = Date.now();
return data;
}
4. Monitor Compliance Regularly
Set up automated monitoring:
// Run daily
async function dailyComplianceCheck() {
const incomplete = await findIncompleteForms();
const expiring = await findExpiringForms(30);
const report = {
date: new Date().toLocaleDateString(),
incomplete_total: incomplete.all.length,
overdue: incomplete.overdue.length,
expiring_soon: expiring.length
};
// Alert if thresholds exceeded
if (report.overdue > 0 || report.expiring_soon > 5) {
await sendAlert({
type: 'compliance_alert',
report
});
}
console.log('Daily compliance check:', report);
}
5. Track Compliance Metrics
Monitor compliance rates over time:
async function trackComplianceMetrics() {
const dashboard = await generateComplianceDashboard();
await db.metrics.create({
date: new Date(),
total_forms: dashboard.total_forms,
compliance_rate: dashboard.compliance_rate,
incomplete: dashboard.by_state.INCOMPLETE,
complete: dashboard.by_state.COMPLETE,
expired: dashboard.by_state.EXPIRED,
overdue: dashboard.overdue,
expiring_soon: dashboard.expiring_soon
});
console.log('Metrics tracked:', dashboard);
}
Common Workflows
Weekly Compliance Report
async function generateWeeklyReport() {
const dashboard = await generateComplianceDashboard();
const incomplete = await findIncompleteForms();
const expiring = await findExpiringForms(30);
const report = {
week_ending: new Date().toLocaleDateString(),
summary: {
total_forms: dashboard.total_forms,
compliance_rate: `${dashboard.compliance_rate}%`,
unique_merchants: dashboard.unique_merchants
},
by_state: dashboard.by_state,
action_items: {
overdue_forms: incomplete.overdue.length,
expiring_within_30_days: expiring.length
}
};
// Send to compliance team
await sendEmail('compliance@company.com', {
subject: `Weekly Compliance Report - ${report.week_ending}`,
template: 'weekly_compliance_report',
data: report
});
console.log('Weekly report generated:', report);
}
Merchant Onboarding Compliance Check
async function checkMerchantCompliance(merchantId) {
const forms = await getMerchantForms(merchantId);
const isCompliant = forms.by_state.INCOMPLETE === 0 &&
forms.by_state.EXPIRED === 0;
if (!isCompliant) {
console.warn(`Merchant ${merchantId} is not compliant`);
console.warn('Incomplete:', forms.by_state.INCOMPLETE);
console.warn('Expired:', forms.by_state.EXPIRED);
} else {
console.log(`✓ Merchant ${merchantId} is compliant`);
}
return {
merchant_id: merchantId,
is_compliant: isCompliant,
forms: forms
};
}