Fetch a Compliance Form
Retrieve a Compliance Form by its ID to check completion status, download forms, or verify compliance details.
Overview
Use this endpoint to:
- Check form status (INCOMPLETE, COMPLETE, or EXPIRED)
- Download unsigned forms for merchant review
- Download signed forms for record-keeping
- Verify signature details and timestamps
- Monitor validity periods and expiration dates
- Track compliance for individual merchants
Use Cases
1. Check Form Completion Status
Verify if a compliance form has been completed:
async function checkFormStatus(formId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms/${formId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
console.log('Form Status:', {
id: form.id,
state: form.state,
type: form.type,
due_date: form.due_at,
valid_until: form.valid_until
});
return form.state === 'COMPLETE';
}
2. Get Form for Merchant Review
Retrieve unsigned form for merchant to review:
async function getFormForReview(formId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms/${formId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
if (form.state === 'COMPLETE') {
console.log('Form already completed');
return {
form,
unsigned_file: form.unsigned_file,
signed_file: form.signed_file,
needs_review: false
};
}
if (form.state === 'EXPIRED') {
console.log('Form has expired');
throw new Error('Compliance form has expired. Contact support for renewal.');
}
// Form is INCOMPLETE - provide for review
console.log('Form ready for review:', {
unsigned_file: form.unsigned_file,
due_date: form.due_at,
days_until_due: Math.ceil((new Date(form.due_at) - new Date()) / (1000 * 60 * 60 * 24))
});
return {
form,
unsigned_file: form.unsigned_file,
needs_review: true
};
}
3. Download Signed Document
Retrieve the signed compliance document:
async function downloadSignedDocument(formId, saveDirectory) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms/${formId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
if (form.state !== 'COMPLETE') {
throw new Error(`Cannot download signed document: form is ${form.state}`);
}
if (!form.signed_file) {
throw new Error('Signed file URL not available');
}
// Download the signed PDF
const pdfResponse = await fetch(form.signed_file);
const pdfBlob = await pdfResponse.blob();
const filename = `${saveDirectory}/compliance_${form.id}_signed.pdf`;
await saveFile(filename, pdfBlob);
console.log('Signed document downloaded:', filename);
return {
local_file: filename,
signed_at: form.pci_saq_a?.signed_at,
signer: form.pci_saq_a?.name,
valid_until: form.valid_until
};
}
4. Verify Signature Details
Check who signed the form and when:
async function verifySignature(formId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms/${formId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
if (form.state !== 'COMPLETE' || !form.pci_saq_a) {
console.log('Form not completed - no signature available');
return null;
}
const signature = {
signer_name: form.pci_saq_a.name,
signer_title: form.pci_saq_a.title,
signed_at: new Date(form.pci_saq_a.signed_at),
ip_address: form.pci_saq_a.ip_address,
user_agent: form.pci_saq_a.user_agent
};
console.log('Signature Details:', signature);
// Verify signature timestamp is within validity period
const signedDate = signature.signed_at;
const validFrom = new Date(form.valid_from);
const validUntil = new Date(form.valid_until);
const isValid = signedDate >= validFrom && signedDate <= validUntil;
console.log('Signature validity:', {
is_valid: isValid,
signed_at: signedDate.toISOString(),
valid_from: validFrom.toISOString(),
valid_until: validUntil.toISOString()
});
return {
...signature,
is_valid: isValid
};
}
5. Monitor Form Expiration
Check if form is expiring soon:
async function checkFormExpiration(formId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms/${formId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
const now = new Date();
const validUntil = new Date(form.valid_until);
const daysUntilExpiration = Math.ceil((validUntil - now) / (1000 * 60 * 60 * 24));
const status = {
id: form.id,
state: form.state,
valid_until: form.valid_until,
days_until_expiration: daysUntilExpiration,
is_expired: validUntil < now,
expires_soon: daysUntilExpiration > 0 && daysUntilExpiration <= 30
};
if (status.is_expired) {
console.warn('⚠️ Form has EXPIRED');
} else if (status.expires_soon) {
console.warn(`⚠️ Form expires in ${daysUntilExpiration} days`);
} else {
console.log(`✓ Form valid for ${daysUntilExpiration} days`);
}
return status;
}
6. Display Form in Dashboard
Get form details for admin dashboard:
async function getFormForDashboard(formId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms/${formId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
const dashboardData = {
id: form.id,
created: new Date(form.created_at).toLocaleDateString(),
merchant_id: form.linked_to,
type: form.type,
state: form.state,
state_color: {
'INCOMPLETE': 'yellow',
'COMPLETE': 'green',
'EXPIRED': 'red'
}[form.state],
due_date: new Date(form.due_at).toLocaleDateString(),
valid_from: new Date(form.valid_from).toLocaleDateString(),
valid_until: new Date(form.valid_until).toLocaleDateString(),
signer: form.pci_saq_a?.name || 'Not signed',
signed_date: form.pci_saq_a?.signed_at
? new Date(form.pci_saq_a.signed_at).toLocaleDateString()
: 'N/A',
unsigned_file: form.unsigned_file,
signed_file: form.signed_file || 'N/A'
};
console.log('Dashboard Data:', dashboardData);
return dashboardData;
}
7. Compliance Audit Report
Generate audit report for a form:
async function generateAuditReport(formId) {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms/${formId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
const report = {
// Form identification
form_id: form.id,
form_type: form.type,
created_at: form.created_at,
updated_at: form.updated_at,
// Merchant information
merchant_id: form.linked_to,
linked_type: form.linked_type,
// Compliance status
current_state: form.state,
due_date: form.due_at,
validity_period: {
from: form.valid_from,
until: form.valid_until
},
// Signature details (if completed)
signature: form.pci_saq_a ? {
signer_name: form.pci_saq_a.name,
signer_title: form.pci_saq_a.title,
signed_at: form.pci_saq_a.signed_at,
ip_address: form.pci_saq_a.ip_address,
user_agent: form.pci_saq_a.user_agent
} : null,
// Documents
documents: {
unsigned_file: form.unsigned_file,
signed_file: form.signed_file
},
// Audit metadata
report_generated_at: new Date().toISOString(),
compliance_status: form.state === 'COMPLETE' ? 'COMPLIANT' : 'NON_COMPLIANT'
};
console.log('Audit Report Generated:', report);
// Export to JSON or PDF
await exportReport(report, `audit_${formId}.json`);
return report;
}
8. Check Multiple Forms for Merchant
Get all compliance forms status for a merchant:
async function getMerchantComplianceStatus(merchantId) {
// First, list all forms for the merchant
const listResponse = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms?linked_to=${merchantId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const listData = await listResponse.json();
const formIds = listData._embedded?.compliance_forms?.map(f => f.id) || [];
// Fetch detailed information for each form
const formDetails = await Promise.all(
formIds.map(async (formId) => {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms/${formId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
return response.json();
})
);
const summary = {
merchant_id: merchantId,
total_forms: formDetails.length,
complete: formDetails.filter(f => f.state === 'COMPLETE').length,
incomplete: formDetails.filter(f => f.state === 'INCOMPLETE').length,
expired: formDetails.filter(f => f.state === 'EXPIRED').length,
forms: formDetails.map(f => ({
id: f.id,
type: f.type,
state: f.state,
due_at: f.due_at,
valid_until: f.valid_until
}))
};
console.log('Merchant Compliance Summary:', summary);
return summary;
}
Response Fields
Core Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique compliance form ID |
created_at | string | Creation timestamp |
updated_at | string | Last update timestamp |
state | string | INCOMPLETE, COMPLETE, or EXPIRED |
type | string | Form type (e.g., PCI_SAQ_A) |
linked_to | string | Merchant ID |
linked_type | string | Entity type (e.g., MERCHANT) |
Date Fields
| Field | Type | Description |
|---|---|---|
due_at | string | When the form is due |
valid_from | string | Start of validity period |
valid_until | string | End of validity period |
Document Fields
| Field | Type | Description |
|---|---|---|
unsigned_file | string | URL to unsigned PDF form |
signed_file | string | URL to signed PDF (if completed) |
Signature Fields (When state is COMPLETE)
| Field | Type | Description |
|---|---|---|
pci_saq_a.name | string | Name of signer |
pci_saq_a.title | string | Title/role of signer |
pci_saq_a.signed_at | string | Signature timestamp |
pci_saq_a.ip_address | string | IP address of signer |
pci_saq_a.user_agent | string | Browser/device user agent |
Best Practices
1. Cache Form Data
Reduce API calls by caching:
const complianceCache = new Map();
const CACHE_TTL = 10 * 60 * 1000; // 10 minutes
async function getCachedComplianceForm(formId) {
const cached = complianceCache.get(formId);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
console.log('Returning cached compliance form');
return cached.data;
}
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms/${formId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
const form = await response.json();
complianceCache.set(formId, {
data: form,
timestamp: Date.now()
});
return form;
}
2. Handle All States
Account for all possible states:
async function handleFormState(formId) {
const form = await getCachedComplianceForm(formId);
switch (form.state) {
case 'INCOMPLETE':
console.log('Form needs completion');
return {
action_required: true,
message: 'Please review and sign the compliance form',
unsigned_file: form.unsigned_file
};
case 'COMPLETE':
console.log('Form is complete');
return {
action_required: false,
message: 'Compliance form completed',
signed_file: form.signed_file,
valid_until: form.valid_until
};
case 'EXPIRED':
console.log('Form has expired');
return {
action_required: true,
message: 'Compliance form has expired. Contact support for renewal.',
expired_at: form.valid_until
};
default:
console.warn('Unknown form state:', form.state);
return {
action_required: true,
message: 'Unknown compliance form state'
};
}
}
3. Monitor Expiration Proactively
Set up alerts for expiring forms:
async function checkAndAlertExpiration(formId, alertThresholdDays = 30) {
const form = await getCachedComplianceForm(formId);
const validUntil = new Date(form.valid_until);
const now = new Date();
const daysRemaining = Math.ceil((validUntil - now) / (1000 * 60 * 60 * 24));
if (daysRemaining <= alertThresholdDays && daysRemaining > 0) {
await sendAlert({
type: 'compliance_expiring',
form_id: formId,
merchant_id: form.linked_to,
days_remaining: daysRemaining,
valid_until: form.valid_until
});
console.log(`Alert sent: Form expires in ${daysRemaining} days`);
}
}
4. Store Documents Securely
Download and archive compliance documents:
async function archiveComplianceDocuments(formId) {
const form = await getCachedComplianceForm(formId);
const documents = {
unsigned: null,
signed: null
};
// Download unsigned form
if (form.unsigned_file) {
const unsignedResponse = await fetch(form.unsigned_file);
const unsignedBlob = await unsignedResponse.blob();
documents.unsigned = await uploadToSecureStorage(
`compliance/${form.id}/unsigned.pdf`,
unsignedBlob
);
}
// Download signed form (if available)
if (form.signed_file) {
const signedResponse = await fetch(form.signed_file);
const signedBlob = await signedResponse.blob();
documents.signed = await uploadToSecureStorage(
`compliance/${form.id}/signed.pdf`,
signedBlob
);
}
console.log('Documents archived:', documents);
return documents;
}
5. Error Handling
Handle errors gracefully:
async function safeGetComplianceForm(formId) {
try {
const response = await fetch(
`https://api.ahrvo.network/payments/na/compliance_forms/${formId}`,
{
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Content-Type': 'application/json'
}
}
);
if (response.status === 404) {
throw new Error('Compliance 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 compliance form:', error);
throw error;
}
}
Common Workflows
Merchant Portal Display
async function displayComplianceInPortal(merchantId) {
// Get all forms for merchant
const forms = await getMerchantComplianceStatus(merchantId);
// Display each form
forms.forms.forEach(form => {
const display = {
title: `${form.type} Form`,
status: form.state,
due_date: new Date(form.due_at).toLocaleDateString(),
action: form.state === 'INCOMPLETE'
? 'Review and Sign'
: 'View Document'
};
console.log('Display:', display);
});
}
Automated Compliance Monitoring
async function monitorComplianceForms() {
// This would run daily
const allMerchants = await getMerchants();
for (const merchant of allMerchants) {
const status = await getMerchantComplianceStatus(merchant.id);
if (status.incomplete > 0 || status.expired > 0) {
await notifyMerchant(merchant.id, {
incomplete: status.incomplete,
expired: status.expired,
forms: status.forms
});
}
}
}