> ## Documentation Index
> Fetch the complete documentation index at: https://gtmapis.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# API Integration Guide

> Integrate email validation into your application

# API Integration Guide

Learn how to integrate GTMAPIs email validation into your application with best practices and real-world examples.

## Quick Integration

### 1. Get Your API Key

First, generate an API key from your [dashboard](https://www.gtmapis.com/dashboard/api-keys):

* **Test keys** (`gtm_test_*`) for development
* **Live keys** (`gtm_live_*`) for production

### 2. Store Securely

Never hardcode API keys. Use environment variables:

<CodeGroup>
  ```bash .env theme={null}
  GTMAPIS_API_KEY=gtm_test_1234567890abcdef1234567890abcdef
  ```

  ```javascript Node.js theme={null}
  // Load from environment
  const apiKey = process.env.GTMAPIS_API_KEY;
  ```

  ```python Python theme={null}
  import os
  api_key = os.environ.get('GTMAPIS_API_KEY')
  ```

  ```go Go theme={null}
  import "os"
  apiKey := os.Getenv("GTMAPIS_API_KEY")
  ```
</CodeGroup>

### 3. Make Your First Request

<CodeGroup>
  ```javascript JavaScript theme={null}
  const validateEmail = async (email) => {
    const response = await fetch('https://api.gtmapis.com/v1/validate', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': process.env.GTMAPIS_API_KEY
      },
      body: JSON.stringify({ email })
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    return await response.json();
  };

  // Usage
  const result = await validateEmail('john@company.com');
  console.log(result.result);  // 'valid', 'invalid', etc.
  ```

  ```python Python theme={null}
  import requests
  import os

  def validate_email(email):
      response = requests.post(
          'https://api.gtmapis.com/v1/validate',
          headers={
              'Content-Type': 'application/json',
              'X-API-Key': os.environ.get('GTMAPIS_API_KEY')
          },
          json={'email': email}
      )
      response.raise_for_status()
      return response.json()

  # Usage
  result = validate_email('john@company.com')
  print(result['result'])
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "net/http"
      "os"
  )

  type ValidationRequest struct {
      Email string `json:"email"`
  }

  type ValidationResult struct {
      Email              string `json:"email"`
      Result             string `json:"result"`
      B2BOutboundQuality string `json:"b2b_outbound_quality"`
      CreditsCharged     int    `json:"credits_charged"`
  }

  func validateEmail(email string) (*ValidationResult, error) {
      body, _ := json.Marshal(ValidationRequest{Email: email})

      req, _ := http.NewRequest("POST", "https://api.gtmapis.com/v1/validate", bytes.NewBuffer(body))
      req.Header.Set("Content-Type", "application/json")
      req.Header.Set("X-API-Key", os.Getenv("GTMAPIS_API_KEY"))

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          return nil, err
      }
      defer resp.Body.Close()

      var result ValidationResult
      json.NewDecoder(resp.Body).Decode(&result)
      return &result, nil
  }
  ```
</CodeGroup>

## Common Integration Patterns

### Sign-Up Form Validation

Validate emails during user registration:

```javascript theme={null}
// React component example
import { useState } from 'react';

export function SignUpForm() {
  const [email, setEmail] = useState('');
  const [validating, setValidating] = useState(false);
  const [validation, setValidation] = useState(null);

  const validateEmail = async () => {
    setValidating(true);

    try {
      const response = await fetch('/api/validate-email', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email })
      });

      const result = await response.json();
      setValidation(result);

      // Show feedback to user
      if (result.result === 'valid') {
        // ✅ Good to go
        return true;
      } else if (result.result === 'valid_role_based') {
        // ⚠️ Warn but allow
        alert('This appears to be a generic email (info@, support@). Consider using a personal email.');
        return true;
      } else {
        // ❌ Block signup
        alert('Please enter a valid email address.');
        return false;
      }
    } finally {
      setValidating(false);
    }
  };

  const handleSubmit = async (e) => {
    e.preventDefault();

    // Validate before submitting
    const isValid = await validateEmail();
    if (isValid) {
      // Proceed with signup
      submitSignUp({ email });
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        onBlur={validateEmail}  // Validate on blur
        required
      />
      {validating && <span>Validating...</span>}
      {validation && (
        <span className={validation.result === 'valid' ? 'text-green-600' : 'text-red-600'}>
          {validation.reason || 'Valid email'}
        </span>
      )}
      <button type="submit">Sign Up</button>
    </form>
  );
}
```

### Lead Import Pipeline

Validate imported leads before adding to CRM:

```javascript theme={null}
async function processLeadImport(leads) {
  const validated = [];
  const rejected = [];

  // Process in batches of 100
  for (let i = 0; i < leads.length; i += 100) {
    const batch = leads.slice(i, i + 100);
    const emails = batch.map(lead => lead.email);

    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 })
    });

    const results = await response.json();

    // Merge results with original leads
    batch.forEach((lead, index) => {
      const validation = results.results[index];

      if (validation.b2b_outbound_quality === 'high') {
        // High-quality lead - add to CRM
        validated.push({
          ...lead,
          email_quality: 'high',
          validation_result: validation
        });
      } else if (validation.result === 'valid_role_based') {
        // Role-based - add with flag
        validated.push({
          ...lead,
          email_quality: 'low',
          is_role_based: true,
          validation_result: validation
        });
      } else {
        // Invalid/risky - reject
        rejected.push({
          ...lead,
          rejection_reason: validation.reason,
          validation_result: validation
        });
      }
    });

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

  return { validated, rejected };
}
```

### Email List Cleaning Service

Build a SaaS email cleaning service:

```javascript theme={null}
// Express.js API endpoint
app.post('/api/clean-list', async (req, res) => {
  const { userId, emails } = req.body;

  try {
    // Check user credits
    const user = await db.users.findById(userId);
    if (user.credits < emails.length * 0.4) {  // Estimate 40% will be charged
      return res.status(402).json({
        error: 'Insufficient credits',
        required: Math.ceil(emails.length * 0.4),
        available: user.credits
      });
    }

    // Validate emails
    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);
    }

    // Deduct credits (only for charged validations)
    const creditsCharged = results.filter(r => r.credits_charged > 0).length;
    await db.users.updateById(userId, {
      credits: user.credits - creditsCharged
    });

    // Save validation history
    await db.validations.create({
      userId,
      totalEmails: emails.length,
      creditsCharged,
      results
    });

    res.json({
      results,
      summary: {
        total: results.length,
        high_quality: results.filter(r => r.b2b_outbound_quality === 'high').length,
        role_based: results.filter(r => r.result === 'valid_role_based').length,
        invalid: results.filter(r => r.result === 'invalid').length,
        credits_charged: creditsCharged
      }
    });
  } catch (error) {
    console.error('Validation error:', error);
    res.status(500).json({ error: 'Validation failed' });
  }
});
```

### Background Job Processing

Process large lists asynchronously:

```javascript theme={null}
// Using BullMQ for job queue
import { Queue, Worker } from 'bullmq';

const validationQueue = new Queue('email-validation');

// Add job
async function queueValidation(userId, emails) {
  await validationQueue.add('validate', {
    userId,
    emails,
    timestamp: Date.now()
  });
}

// Process job
const worker = new Worker('email-validation', async (job) => {
  const { userId, emails } = job.data;

  // Update progress
  await job.updateProgress(0);

  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);

    // Update progress
    const progress = ((i + 100) / emails.length) * 100;
    await job.updateProgress(Math.min(100, progress));

    await new Promise(resolve => setTimeout(resolve, 500));
  }

  // Send notification email
  await sendEmail(userId, {
    subject: 'Email Validation Complete',
    results
  });

  return results;
});
```

## Best Practices

### Error Handling

Always handle errors gracefully:

```javascript theme={null}
async function validateWithRetry(email, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch('https://api.gtmapis.com/v1/validate', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': process.env.GTMAPIS_API_KEY
        },
        body: JSON.stringify({ email })
      });

      if (response.status === 429) {
        // Rate limit - wait and retry
        const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
        console.log(`Rate limited. Retrying after ${retryAfter}s...`);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        continue;
      }

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${await response.text()}`);
      }

      return await response.json();
    } catch (error) {
      if (attempt === maxRetries) {
        console.error(`Failed after ${maxRetries} attempts:`, error);
        throw error;
      }

      // Exponential backoff
      const delay = Math.pow(2, attempt) * 1000;
      console.log(`Attempt ${attempt} failed. Retrying in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
```

### Caching Results

Cache validation results to reduce API calls:

```javascript theme={null}
const cache = new Map();
const CACHE_TTL = 7 * 24 * 60 * 60 * 1000;  // 7 days

async function validateWithCache(email) {
  const cacheKey = email.toLowerCase();

  // Check cache
  const cached = cache.get(cacheKey);
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.result;
  }

  // Validate
  const result = await validateEmail(email);

  // Cache result
  cache.set(cacheKey, {
    result,
    timestamp: Date.now()
  });

  return result;
}
```

### Rate Limit Management

Implement rate limiting on your side:

```javascript theme={null}
import Bottleneck from 'bottleneck';

// Limit to 900 requests/minute (safe margin)
const limiter = new Bottleneck({
  maxConcurrent: 10,  // Concurrent requests
  minTime: 67  // Min 67ms between requests (900/min)
});

// Wrap API calls
const validateEmail = limiter.wrap(async (email) => {
  const response = await fetch('https://api.gtmapis.com/v1/validate', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': process.env.GTMAPIS_API_KEY
    },
    body: JSON.stringify({ email })
  });

  return await response.json();
});
```

## Testing

### Test Mode

Use test keys for development:

```javascript theme={null}
const apiKey = process.env.NODE_ENV === 'production'
  ? process.env.GTMAPIS_LIVE_KEY
  : process.env.GTMAPIS_TEST_KEY;
```

### Mock for Unit Tests

Mock API responses in tests:

```javascript theme={null}
// Jest example
jest.mock('node-fetch');

test('validates email successfully', async () => {
  fetch.mockResolvedValueOnce({
    ok: true,
    json: async () => ({
      email: 'test@example.com',
      result: 'valid',
      b2b_outbound_quality: 'high',
      credits_charged: 1
    })
  });

  const result = await validateEmail('test@example.com');
  expect(result.result).toBe('valid');
});
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Error Handling" icon="bug" href="/guides/error-handling">
    Learn how to handle errors properly
  </Card>

  <Card title="Rate Limits" icon="gauge" href="/guides/rate-limits">
    Understand rate limiting best practices
  </Card>
</CardGroup>
