Skip to main content

Documentation Index

Fetch the complete documentation index at: https://gtmapis.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

CSV Upload Guide

Upload and validate CSV files containing up to 10,000 emails through the GTMAPIs web dashboard.

Prerequisites

Before uploading a CSV:

Step-by-Step Process

1

Prepare Your CSV

Your CSV must contain an email column. Other columns are preserved in the output.
2

Upload to Dashboard

Go to Dashboard and click “Upload CSV”
3

Map Email Column

Select which column contains email addresses
4

Start Validation

Click “Validate” to begin processing
5

Receive Results

Download CSV with validation results or receive via email

CSV Format Requirements

Supported Formats

  • File type: .csv only
  • Max size: 10,000 emails per upload
  • Encoding: UTF-8 recommended
  • Delimiter: Comma (,)

Example Input CSV

email,first_name,last_name,company
john@company.com,John,Doe,Acme Inc
info@company.com,Info,Team,Acme Inc
invalid@notreal.com,Invalid,User,Fake Corp
sarah@startup.io,Sarah,Williams,Startup LLC

Column Mapping

During upload, you’ll select which column contains emails:
  • Preview shows first 5 rows
  • Click on the column header to select
  • System validates format before processing

Output Format

Added Validation Columns

Your output CSV includes 8 new columns with validation results:
ColumnDescriptionExample Values
resultValidation resultvalid, valid_role_based, risky, invalid, unknown
reasonExplanation of result”Valid personal email”, “Role-based email address”
is_role_basedRole-based flagtrue, false
is_free_providerFree provider flagtrue, false
is_catch_allCatch-all flagtrue, false
b2b_outbound_qualityB2B quality scorehigh, low, none
credits_chargedCredits used0, 1
charge_reasonCharge explanation”Valid personal email with high B2B outbound quality”

Example Output CSV

email,first_name,last_name,company,result,reason,is_role_based,is_free_provider,is_catch_all,b2b_outbound_quality,credits_charged,charge_reason
john@company.com,John,Doe,Acme Inc,valid,,false,false,false,high,1,"Valid personal email with high B2B outbound quality"
info@company.com,Info,Team,Acme Inc,valid_role_based,"Role-based email address",true,false,false,low,0,"Role-based email - free for low B2B value"
invalid@notreal.com,Invalid,User,Fake Corp,invalid,"Domain has no MX records",false,false,false,none,0,"Invalid email does not consume credits"
sarah@startup.io,Sarah,Williams,Startup LLC,valid,,false,false,false,high,1,"Valid personal email with high B2B outbound quality"

Processing Details

Batch Processing

The system processes emails in batches:
  1. Deduplication: Removes duplicate emails (case-insensitive)
  2. Batch size: 100 emails per API request
  3. Delay: 500ms between batches to avoid rate limits
  4. Retry logic: Automatic retry on transient failures

Processing Time

EmailsEstimated Time
100~10 seconds
1,000~1-2 minutes
5,000~5-10 minutes
10,000~10-20 minutes
Note: Times vary based on DNS caching and SMTP responsiveness

Email Notification

When validation completes:
  • Email sent to your account address
  • CSV file attached
  • Summary statistics included
  • Notification usually arrives within 1 minute

Credit Usage

How Credits Are Deducted

Credits are deducted AFTER validation:
  1. Upload CSV (no charge yet)
  2. System validates all emails
  3. Counts high-quality results
  4. Deducts only for result: "valid" + b2b_outbound_quality: "high"
  5. Returns results

Example Credit Usage

Uploaded CSV: 1,000 emails
ResultCountCredits
Valid personal400400
Role-based2500 (FREE)
Catch-all2000 (FREE)
Invalid1500 (FREE)
Total1,000400
**Cost at 0.001/credit:0.001/credit**: 0.40 (60% savings vs charging for all)

Insufficient Credits

If you don’t have enough credits:
  • Upload is rejected before processing
  • Error message shows required vs available
  • No partial processing (all-or-nothing)
Solution: Purchase more credits or reduce batch size

Best Practices

Before Uploading

Remove obvious invalids and duplicates locally:
// Remove duplicates
const unique = [...new Set(emails.map(e => e.toLowerCase()))];

// Basic syntax filter
const validFormat = unique.filter(e => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e));

// Remove common placeholders
const cleaned = validFormat.filter(e =>
  !e.includes('example.com') &&
  !e.includes('test@') &&
  !e.includes('@test.')
);
Check your CSV before uploading:
  • Proper comma delimiters
  • No missing headers
  • Consistent column count per row
  • UTF-8 encoding (especially for international names)
  • No BOM (Byte Order Mark) issues
Before processing 10,000 emails:
  1. Extract first 100 rows
  2. Upload test batch
  3. Review results quality
  4. Adjust source or filters if needed
  5. Process full list

After Validation

Separate emails by B2B quality:
// High quality for primary campaigns
const highQuality = results.filter(r =>
  r.result === 'valid' && r.b2b_outbound_quality === 'high'
);

// Role-based for secondary outreach
const roleBased = results.filter(r =>
  r.result === 'valid_role_based'
);

// Remove these completely
const toRemove = results.filter(r =>
  r.result === 'invalid' || r.result === 'risky'
);
Keep records of validations:
  • Original upload date
  • Source of emails
  • Validation results summary
  • Credits consumed
  • Campaign performance per quality tier
Re-validate lists every 3-6 months as emails change
Compare campaign performance by quality:
High Quality Emails:
- Open rate: 25-35%
- Response rate: 5-10%
- Cost per lead: $X

Role-Based Emails:
- Open rate: 10-15%
- Response rate: 1-2%
- Cost per lead: $X * 5

Risky/Invalid:
- Bounce rate: 50-80%
- Damages sender reputation
- Cost: Wasted credits

Common Issues

CSV Upload Fails

Problem: “Invalid CSV format” error Causes:
  • Non-UTF-8 encoding
  • Inconsistent column counts
  • Missing headers
  • Special characters in data
Solution:
  1. Open CSV in text editor
  2. Check for encoding issues
  3. Verify all rows have same column count
  4. Remove special characters or escape properly

No Email Column Detected

Problem: System can’t find email column Causes:
  • Column named something other than “email”
  • Emails in wrong format
  • Empty column
Solution:
  1. Rename column to “email” (lowercase)
  2. Verify emails are in user@domain.com format
  3. Check first few rows have valid data

Processing Takes Too Long

Problem: Validation stuck or timing out Causes:
  • Large batch size
  • Many slow SMTP servers
  • Network issues
Solution:
  1. Check processing status in dashboard
  2. Wait for email notification
  3. If > 30 minutes, contact support
  4. Try smaller batches (< 5,000 emails)

Unexpected Credit Charges

Problem: Charged more credits than expected Causes:
  • Misunderstanding of credit system
  • More high-quality emails than estimated
  • Duplicates not removed
Solution:
  1. Check CSV for duplicate emails
  2. Review validation results
  3. Filter by credits_charged column
  4. Only valid + b2b_outbound_quality: "high" are charged

Programmatic CSV Validation

For automation, use the API directly:
const fs = require('fs');
const Papa = require('papaparse');

async function validateCSV(filePath) {
  // 1. Read CSV
  const csvData = fs.readFileSync(filePath, 'utf8');
  const parsed = Papa.parse(csvData, { header: true });

  // 2. Extract emails
  const emails = parsed.data.map(row => row.email).filter(Boolean);

  // 3. Validate in batches
  const results = [];
  for (let i = 0; i < emails.length; i += 100) {
    const batch = emails.slice(i, i + 100);

    const response = await fetch('https://api.gtmapis.com/v1/validate/bulk', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': process.env.GTMAPIS_API_KEY
      },
      body: JSON.stringify({ emails: batch })
    });

    const batchResults = await response.json();
    results.push(...batchResults.results);

    // Rate limit delay
    await new Promise(resolve => setTimeout(resolve, 500));
  }

  // 4. Merge results with original data
  const merged = parsed.data.map(row => {
    const result = results.find(r => r.email === row.email);
    return { ...row, ...result };
  });

  // 5. Write output CSV
  const csv = Papa.unparse(merged);
  fs.writeFileSync('output.csv', csv);

  console.log(`Validated ${results.length} emails`);
  return merged;
}

Next Steps

Upload CSV Now

Start validating your email list

API Integration

Integrate validation into your app