Skip to main content

Overview

Document Requests enable you to collect files from external parties (customers, applicants, claimants) without requiring them to create an account. This feature streamlines document collection workflows by sending secure, time-limited upload links via email.
Key Benefit: External parties can upload documents through a branded, secure interface without authentication, while you maintain full control and visibility.

How Document Requests Work

Document Requests automate the collection process:
  1. You create a request with recipient details and expiration date
  2. System sends automated email with secure upload link to recipient
  3. Recipient uploads files through branded interface (no account needed)
  4. You monitor progress and retrieve uploaded files
  5. Analysis happens automatically once files are uploaded
1

Create Request

Define recipient, expiration, and file limits
2

Email Sent

Automated invitation with secure JWT-protected link
3

Guest Upload

Recipient uploads files without authentication
4

Analysis

Files automatically analysed upon upload
5

Retrieve Results

Access uploaded files and analysis results

Use Cases

Insurance Claims

Request accident photos, repair estimates, and supporting documents from claimants

Loan Applications

Collect bank statements, payslips, and tax documents from applicants

Customer Onboarding

Gather identity documents, proof of address, and compliance paperwork

Vendor Verification

Request business registrations, tax certificates, and director IDs

Creating Document Requests

Basic Request Creation

Create a document request with essential details:
const response = await fetch('https://api.{region}.veridox.ai/document-requests/create', {
  method: 'POST',
  headers: {
    'X-API-Key': 'vdx_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    label: 'Insurance Claim #CLM-2026-001',
    recipient_email: 'customer@email.com',
    recipient_name: 'John Smith',
    expires_at: '2026-02-15T23:59:59.000Z',
    max_files: 10,
    email_message: 'Please upload photos of the damage, repair estimates, and any witness statements.'
  })
});

const request = await response.json();
console.log('Request created:', request.id);
console.log('Associated case:', request.case_id);
API Reference: See Create Document Request for complete documentation.

Request Parameters

ParameterRequiredDescriptionValidation
labelYesDescriptive request nameMax 200 characters
recipient_emailYesEmail address to send invitationValid email format
expires_atYesRequest expiration date/timeISO 8601, must be future
max_filesYesMaximum files recipient can upload1-20
recipient_nameNoRecipient name for personalizationMax 200 characters
email_messageNoCustom message in email invitationMax 1000 characters

Setting Expiration Dates

Choose appropriate expiration based on use case:
// 48 hours for urgent claims
const expiresAt = new Date();
expiresAt.setHours(expiresAt.getHours() + 48);

const request = await createDocumentRequest({
  label: 'Urgent: Accident Claim Evidence',
  recipient_email: 'claimant@insurance.com',
  expires_at: expiresAt.toISOString(),
  max_files: 5,
  email_message: 'URGENT: Please upload accident photos within 48 hours.'
});

Request Lifecycle

Status Progression

Document requests transition through three states:

Expired State

Automatic expiration when time limit reached:
  • Link becomes inactive
  • No uploads possible
  • Request marked as expired
  • Can create new request if needed

Monitoring Requests

List All Requests

Retrieve requests with filtering and pagination:
// Get all pending requests belonging to you
const response = await fetch(
  'https://api.{region}.veridox.ai/document-requests?status=pending&limit=20',
  {
    headers: { 'X-API-Key': 'vdx_your_api_key' }
  }
);

const { links, total } = await response.json();

console.log(`Total pending requests: ${total}`);

links.forEach(request => {
  console.log(`${request.label}: ${request.uploaded_files_count}/${request.max_files} files`);
  console.log(`  Expires: ${new Date(request.expires_at).toLocaleDateString()}`);
  console.log(`  Accessed: ${request.access_count} times`);
});
API Reference: See List Document Requests for filtering options.

Get Request Details

Monitor individual request progress:
const requestId = '019c003f-3c82-72a2-99b6-267e331692c0';

const response = await fetch(
  `https://api.{region}.veridox.ai/document-requests/${requestId}`,
  {
    headers: { 'X-API-Key': 'vdx_your_api_key' }
  }
);

const request = await response.json();

console.log('Status:', request.status);
console.log('Files uploaded:', request.uploaded_files_count);
console.log('Last accessed:', request.last_accessed_at);

if (request.completed_at) {
  console.log('Completed at:', request.completed_at);
}
API Reference: See Get Document Request for complete response schema.

Tracking Metrics

Monitor key metrics for request performance:
async function getRequestMetrics(requests) {
  return requests.reduce((metrics, request) => {
    // Completion rate
    if (request.status === 'completed') {
      metrics.completed++;
    }

    // Access rate (recipient opened link)
    if (request.access_count > 0) {
      metrics.accessed++;
    }

    // Upload rate (at least one file uploaded)
    if (request.uploaded_files_count > 0) {
      metrics.uploaded++;
    }

    // Expiration without completion
    if (request.status === 'expired' && request.uploaded_files_count === 0) {
      metrics.expired_unused++;
    }

    return metrics;
  }, {
    completed: 0,
    accessed: 0,
    uploaded: 0,
    expired_unused: 0
  });
}

// Usage
const allRequests = await fetchAllRequests();
const metrics = getRequestMetrics(allRequests);

console.log('Completion rate:', (metrics.completed / allRequests.length * 100).toFixed(1) + '%');
console.log('Access rate:', (metrics.accessed / allRequests.length * 100).toFixed(1) + '%');
console.log('Upload rate:', (metrics.uploaded / allRequests.length * 100).toFixed(1) + '%');

Managing Requests

Resending Invitations

Resend invitation email if recipient didn’t receive original:
const requestId = '019c003f-3c82-72a2-99b6-267e331692c0';

const response = await fetch(
  `https://api.{region}.veridox.ai/document-requests/${requestId}/resend`,
  {
    method: 'POST',
    headers: {
      'X-API-Key': 'vdx_your_api_key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      email_message: 'Resending: Please upload the required documents for your claim.'
    })
  }
);

if (response.ok) {
  console.log('Invitation resent successfully');
}
API Reference: See Resend Document Request for details.
When to Resend:
  • Recipient reports not receiving email (check spam folders first)
  • Original email expired or deleted
  • Need to update custom message with additional instructions
  • Following up on pending requests

Canceling Requests

Delete requests that are no longer needed:
const requestId = '019c003f-3c82-72a2-99b6-267e331692c0';

const response = await fetch(
  `https://api.{region}.veridox.ai/document-requests/${requestId}`,
  {
    method: 'DELETE',
    headers: { 'X-API-Key': 'vdx_your_api_key' }
  }
);

if (response.ok) {
  console.log('Request deleted successfully');
}
API Reference: See Delete Document Request for details.
When to Cancel:
  • Request sent to wrong recipient
  • Information requirements changed
  • Applicant withdrew application
  • Duplicate request created by mistake
Deletion is Permanent: Deleting a request also deactivates the upload link immediately. Recipient will no longer be able to access the link.

Retrieving Uploaded Files

Accessing Files Through Cases

All uploads are associated with a case for analysis:
// Get request details to find case ID
const request = await fetch(
  `https://api.{region}.veridox.ai/document-requests/${requestId}`,
  { headers: { 'X-API-Key': apiKey } }
).then(r => r.json());

// Get case details with uploaded files
const caseData = await fetch(
  `https://api.{region}.veridox.ai/cases/${request.case_id}`,
  { headers: { 'X-API-Key': apiKey } }
).then(r => r.json());

console.log('Case files:', caseData.files.length);

// Access each file's analysis
for (const file of caseData.files) {
  console.log(`File: ${file.label}`);
  console.log(`  Risk: ${file.current_risk_score || 'pending'}`);
  console.log(`  Status: ${file.analysis_status}`);
}

Complete Retrieval Workflow

async function processDocumentRequestUploads(requestId) {
  // 1. Get request details
  const request = await fetch(
    `https://api.{region}.veridox.ai/document-requests/${requestId}`,
    { headers: { 'X-API-Key': apiKey } }
  ).then(r => r.json());

  if (request.status !== 'completed') {
    console.log('Request not yet completed');
    return;
  }

  // 2. Get associated case
  const caseData = await fetch(
    `https://api.{region}.veridox.ai/cases/${request.case_id}`,
    { headers: { 'X-API-Key': apiKey } }
  ).then(r => r.json());

  console.log(`Processing ${caseData.files.length} uploaded files`);

  // 3. Get detailed analysis for each file
  const analyses = await Promise.all(
    caseData.files.map(file =>
      fetch(
        `https://api.{region}.veridox.ai/files/${file.file_id}/analysis`,
        { headers: { 'X-API-Key': apiKey } }
      ).then(r => r.json())
    )
  );

  // 4. Process results
  const results = analyses.map((analysis, index) => ({
    file: caseData.files[index],
    riskScore: analysis.current_risk_score,
    summary: analysis.analysis_results?.full_analysis?.summary,
    findings: analysis.analysis_results?.full_analysis?.findings || []
  }));

  return results;
}

// Usage
const results = await processDocumentRequestUploads(requestId);

results.forEach(({ file, riskScore, summary }) => {
  console.log(`\n${file.label}:`);
  console.log(`  Risk: ${riskScore}`);
  console.log(`  ${summary}`);
});

Email Invitation

Email Content

Recipients receive a professional email containing:
  • Subject: Customised with your label (e.g., “Document Request: Insurance Claim #CLM-2026-001”)
  • Recipient Name: Personalised greeting (if name provided)
  • Custom Message: Your specific instructions
  • Upload Link: Secure JWT-protected URL
  • Expiration Notice: Clear deadline
  • Support Contact: Help information

Email Customization

Provide clear, actionable instructions:
{
  label: 'Car Accident Claim - POL-2026-001',
  recipient_email: 'customer@insurance.com',
  recipient_name: 'Sarah Johnson',
  email_message: `Please upload the following documents for your claim:

1. Photos of vehicle damage (all angles)
2. Repair estimate from approved mechanic
3. Police report (if applicable)
4. Witness statements (if available)

If you have questions, contact your claims adjuster at claims@insurance.com.`,
  max_files: 15,
  expires_at: expiresIn(14, 'days')
}

Automation Patterns

Automated Request Creation

Create requests automatically from business events:
// Example: Create request when insurance claim is filed
async function handleNewClaim(claim) {
  const expiresAt = new Date();
  expiresAt.setDate(expiresAt.getDate() + 14);

  const request = await fetch('https://api.{region}.veridox.ai/document-requests/create', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.VERIDOX_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      label: `Insurance Claim ${claim.claimNumber}`,
      recipient_email: claim.customerEmail,
      recipient_name: claim.customerName,
      expires_at: expiresAt.toISOString(),
      max_files: 10,
      email_message: `Please upload all documentation related to claim ${claim.claimNumber}. Include damage photos, repair estimates, and any police reports.`
    })
  }).then(r => r.json());

  // Store request ID with claim record
  await database.claims.update(claim.id, {
    documentRequestId: request.id,
    documentRequestStatus: 'pending'
  });

  return request;
}

Follow-Up Reminders

Send reminders for pending requests:
async function sendReminders() {
  // Get pending requests expiring soon
  const requests = await fetch(
    'https://api.{region}.veridox.ai/document-requests?status=pending',
    { headers: { 'X-API-Key': apiKey } }
  ).then(r => r.json());

  const now = new Date();
  const threeDaysFromNow = new Date(now.getTime() + 3 * 24 * 60 * 60 * 1000);

  for (const request of requests.links) {
    const expiresAt = new Date(request.expires_at);

    // Send reminder if expiring in 3 days and no uploads yet
    if (expiresAt <= threeDaysFromNow && request.uploaded_files_count === 0) {
      await fetch(
        `https://api.{region}.veridox.ai/document-requests/${request.id}/resend`,
        {
          method: 'POST',
          headers: {
            'X-API-Key': apiKey,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            email_message: `REMINDER: Your document upload link expires in 3 days. Please upload the required documents as soon as possible.`
          })
        }
      );

      console.log(`Reminder sent for request: ${request.label}`);
    }
  }
}

// Run daily
setInterval(sendReminders, 24 * 60 * 60 * 1000);

Webhooks Integration

You can use webhooks to receive automatic notifications when document request events occur, such as a request being completed. This enables automated workflows like risk-based escalation and auto-approval.

Best Practices

Request Creation

Descriptive labels - Include identifiers (claim numbers, application IDs) for easy tracking
Clear instructions - Specify exactly what documents are needed and formatting requirements
Appropriate expiration - Balance urgency with recipient availability (7-30 days typical)
Realistic file limits - Consider document types and allow buffer for unexpected files

Email Communication

Professional tone - Use clear, respectful language in custom messages
Actionable guidance - List specific documents needed and acceptance criteria
Contact information - Provide support contact for questions
Deadline clarity - Clearly state expiration date and consequences

Monitoring and Follow-Up

Track access rates - Monitor if recipients are opening links
Send reminders - Follow up on pending requests before expiration
Analyse completion rates - Identify patterns in successful vs. failed requests
Automate workflows - Create requests automatically from business events

Security

Validate recipients - Verify email addresses before sending
Appropriate expiration - Don’t set excessively long expiration periods
Monitor unusual activity - Watch for suspicious upload patterns
Access control - Users can only access document requests they have created
Audit access - Review access counts and timestamps regularly

Rate Limits

Document request operations are rate-limited:
OperationLimitScopeWindow
Create request10 requestsPer IP addressPer minute
List requests30 requestsPer IP addressPer minute
Get request details60 requestsPer organisationPer minute
Resend invitation5 requestsPer IP addressPer minute
Best Practice: Cache request data and use pagination to stay within limits. See Error Handling for retry strategies.

Common Issues

Email Not Received

Problem: Recipient reports not receiving invitation email Solutions:
  • Check spam/junk folders
  • Verify email address is correct
  • Resend invitation
  • Check email service provider’s spam filters
  • Whitelist Veridox sending domain
Problem: Recipient tries to access expired link Solutions:
  • Create new document request with updated expiration
  • Consider longer expiration periods for future requests
  • Set up automated reminder emails before expiration

Upload Limit Reached

Problem: Recipient needs to upload more files than max_files allows Solutions:
  • Delete request and create new one with higher limit
  • Request recipient to combine documents (e.g., multi-page PDF)
  • Create second request for additional documents

Files Not Analysed

Problem: Uploaded files not showing analysis results Solutions:
  • Check case analysis status via progress endpoints
  • Large files may take 3-5 minutes to analyse
  • Verify files are supported formats (PDF, JPEG, PNG)
  • Contact support if analysis exceeds 10 minutes

Troubleshooting

Request Status Not Updating

Check request details to verify current state:
const request = await fetch(
  `https://api.{region}.veridox.ai/document-requests/${requestId}`,
  { headers: { 'X-API-Key': apiKey } }
).then(r => r.json());

console.log('Status:', request.status);
console.log('Files uploaded:', request.uploaded_files_count);
console.log('Last updated:', request.updated_at);

Recipient Upload Failures

Common causes and solutions:
IssueCauseSolution
Link won’t openExpired or deleted requestCreate new request
File upload failsFile too large (>20 MB)Request smaller file or PDF
Max files reachedLimit exceededDelete request, create with higher limit
JWT token invalidLink tampered withResend original invitation

Analysis Not Completing

Monitor case analysis progress:
// Check if analysis is still processing
const caseData = await fetch(
  `https://api.{region}.veridox.ai/cases/${request.case_id}`,
  { headers: { 'X-API-Key': apiKey } }
).then(r => r.json());

caseData.files.forEach(file => {
  console.log(`${file.label}: ${file.analysis_status}`);
});

Create Request API

Detailed API reference for creating document requests

List Requests API

Retrieve and filter document requests

Get Request API

Get detailed request status and metrics

Resend Invitation API

Resend email invitations to recipients

Delete Request API

Cancel and delete document requests

Case Management

Understanding cases and file organisation

Document Analysis

How uploaded documents are analysed

Error Handling

Handling API errors and rate limits