> ## 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.

# Validate Single Email

> Validate a single email address

# POST /v1/validate

Validate a single email address through the 4-layer validation pipeline.

## Endpoint

```
POST https://api.gtmapis.com/v1/validate
```

## Headers

| Header         | Required | Description                                 |
| -------------- | -------- | ------------------------------------------- |
| `Content-Type` | Yes      | Must be `application/json`                  |
| `X-API-Key`    | Yes      | Your API key (`gtm_test_*` or `gtm_live_*`) |

## Request Body

| Field   | Type   | Required | Description                   |
| ------- | ------ | -------- | ----------------------------- |
| `email` | string | Yes      | The email address to validate |

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.gtmapis.com/v1/validate \
    -H "Content-Type: application/json" \
    -H "X-API-Key: gtm_test_1234567890abcdef1234567890abcdef" \
    -d '{"email":"john@company.com"}'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.gtmapis.com/v1/validate', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': 'gtm_test_1234567890abcdef1234567890abcdef'
    },
    body: JSON.stringify({
      email: 'john@company.com'
    })
  });

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

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

  response = requests.post(
      'https://api.gtmapis.com/v1/validate',
      headers={
          'Content-Type': 'application/json',
          'X-API-Key': 'gtm_test_1234567890abcdef1234567890abcdef'
      },
      json={'email': 'john@company.com'}
  )

  result = response.json()
  ```

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

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

  func main() {
      body := map[string]string{"email": "john@company.com"}
      jsonBody, _ := json.Marshal(body)

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

      client := &http.Client{}
      resp, _ := client.Do(req)
      defer resp.Body.Close()
  }
  ```
</CodeGroup>

## Response

### Success Response (200 OK)

#### Valid Personal Email

```json theme={null}
{
  "email": "john@company.com",
  "result": "valid",
  "reason": "",
  "syntax_valid": true,
  "dns_valid": true,
  "smtp_valid": true,
  "is_role_based": false,
  "is_catchall": false,
  "b2b_outbound_quality": "high",
  "b2b_quality": "high",
  "credits_charged": 1,
  "charge_reason": "Valid personal email with high B2B outbound quality"
}
```

#### Role-Based Email (FREE)

```json theme={null}
{
  "email": "info@company.com",
  "result": "valid_role_based",
  "reason": "Role-based email address",
  "syntax_valid": true,
  "dns_valid": true,
  "smtp_valid": true,
  "is_role_based": true,
  "role_type": "information",
  "b2b_outbound_quality": "low",
  "b2b_quality": "low",
  "credits_charged": 0,
  "charge_reason": "Role-based email - free for low B2B value"
}
```

#### Catch-All Domain (FREE)

```json theme={null}
{
  "email": "anyone@catchall.com",
  "result": "risky",
  "reason": "Catch-all domain detected",
  "syntax_valid": true,
  "dns_valid": true,
  "smtp_valid": false,
  "is_role_based": false,
  "is_catchall": true,
  "catchall_confidence": "high",
  "b2b_outbound_quality": "none",
  "b2b_quality": "none",
  "credits_charged": 0,
  "charge_reason": "Catch-all domain - cannot verify individual mailbox"
}
```

#### Invalid Email (FREE)

```json theme={null}
{
  "email": "notreal@fakeemail123.com",
  "result": "invalid",
  "reason": "Domain has no MX records",
  "syntax_valid": true,
  "dns_valid": false,
  "smtp_valid": false,
  "validation_layer": "dns",
  "b2b_outbound_quality": "none",
  "b2b_quality": "none",
  "credits_charged": 0,
  "charge_reason": "Invalid email does not consume credits"
}
```

#### Unknown Verification (FREE)

```json theme={null}
{
  "email": "john@restrictive.com",
  "result": "unknown",
  "reason": "SMTP verification not permitted",
  "syntax_valid": true,
  "dns_valid": true,
  "smtp_valid": false,
  "smtp_response": "550 5.7.1 Recipient verification not allowed",
  "b2b_outbound_quality": "unknown",
  "b2b_quality": "unknown",
  "credits_charged": 0,
  "charge_reason": "Unable to verify - no credit charged"
}
```

### Response Fields

<ResponseField name="email" type="string" required>
  The validated email address
</ResponseField>

<ResponseField name="result" type="string" required>
  Validation result: `valid`, `valid_role_based`, `risky`, `invalid`, or `unknown`

  See [Result Categories](/concepts/result-categories) for details
</ResponseField>

<ResponseField name="reason" type="string">
  Human-readable explanation of the validation result
</ResponseField>

<ResponseField name="is_role_based" type="boolean" required>
  `true` if the email is a generic business inbox (info@, support@, etc.)
</ResponseField>

<ResponseField name="is_free_provider" type="boolean">
  `true` if the domain is a free email provider (Gmail, Yahoo, Outlook, etc.)
</ResponseField>

<ResponseField name="is_catchall" type="boolean">
  `true` if the domain accepts all email addresses (can't verify specific mailbox)
</ResponseField>

<ResponseField name="catchall_confidence" type="string">
  Confidence level: `high`, `medium`, or `low` (only present if `is_catchall` is true)
</ResponseField>

<ResponseField name="b2b_outbound_quality" type="string" required>
  B2B outbound value: `high` (worth using), `low` (role-based), `none` (invalid/risky), or `unknown`

  See [B2B Quality Scoring](/concepts/b2b-quality-scoring) for details
</ResponseField>

<ResponseField name="credits_charged" type="integer" required>
  Number of credits charged: `0` (free) or `1` (charged)

  Only `valid` personal emails with `b2b_outbound_quality: "high"` are charged
</ResponseField>

<ResponseField name="charge_reason" type="string" required>
  Explanation of why credits were or weren't charged
</ResponseField>

<ResponseField name="role_type" type="string">
  Category of role-based email (e.g., "information", "support", "sales")

  Only present if `is_role_based` is true
</ResponseField>

<ResponseField name="validation_layer" type="string">
  Layer where validation stopped: `syntax`, `dns`, `smtp`, or `catchall`

  Useful for debugging failures
</ResponseField>

<ResponseField name="smtp_response" type="string">
  Raw SMTP server response (when applicable)

  Useful for understanding SMTP-level issues
</ResponseField>

### Error Responses

#### 400 Bad Request

```json theme={null}
{
  "error": "Bad Request",
  "message": "Email field is required"
}
```

**Common causes**:

* Missing `email` field
* Empty email string
* Malformed JSON

#### 401 Unauthorized

```json theme={null}
{
  "error": "Unauthorized",
  "message": "Invalid API key"
}
```

**Common causes**:

* Missing `X-API-Key` header
* Invalid or revoked API key
* Incorrect API key format

#### 429 Too Many Requests

```json theme={null}
{
  "error": "Rate limit exceeded",
  "message": "You have exceeded the rate limit of 10000 requests per minute",
  "retry_after": 60
}
```

**Solution**: Wait for the `retry_after` seconds before making more requests

#### 500 Internal Server Error

```json theme={null}
{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred"
}
```

**Solution**: Retry the request or contact support if the issue persists

## Performance

* **Cached DNS**: \~50ms average
* **Uncached DNS**: \~500ms average
* **Full SMTP validation**: \~2s average

## Best Practices

### Error Handling

Always handle all possible result types:

```javascript theme={null}
const result = await validateEmail('john@company.com');

switch (result.result) {
  case 'valid':
    // High-value email - use in campaigns
    if (result.b2b_outbound_quality === 'high') {
      addToCampaign(result.email);
    }
    break;

  case 'valid_role_based':
    // Low-value email - use with caution
    addToSecondaryList(result.email);
    break;

  case 'risky':
    // Catch-all - avoid in campaigns
    markAsRisky(result.email);
    break;

  case 'invalid':
    // Remove from list
    removeFromList(result.email);
    break;

  case 'unknown':
    // Can't verify - test carefully
    addToTestList(result.email);
    break;
}
```

### Rate Limiting

For high-volume validation, use the bulk endpoint:

```javascript theme={null}
// Instead of this (1000 requests)
for (const email of emails) {
  await validateEmail(email);  // ❌ Slow, hits rate limit
}

// Do this (10 requests for 1000 emails)
const chunks = chunkArray(emails, 100);
for (const chunk of chunks) {
  await validateBulk(chunk);  // ✅ Fast, under rate limit
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Bulk Validation" icon="envelopes-bulk" href="/api-reference/validate-bulk">
    Validate up to 100 emails at once
  </Card>

  <Card title="Result Categories" icon="list" href="/concepts/result-categories">
    Understand all validation results
  </Card>
</CardGroup>
