Troubleshooting GuideΒΆ

Common issues and their solutions when integrating with ReputeAPI.


Authentication IssuesΒΆ

401 Unauthorized - Invalid API KeyΒΆ

Symptoms:

{
  "error": "Unauthorized",
  "message": "Invalid or missing API key",
  "status": 401
}

Common Causes:

  1. Missing API key header
  2. Incorrect header name
  3. API key has wrong prefix/format
  4. API key has been revoked

Solutions:

Python:

# ❌ Wrong - Missing header
response = requests.get(f"{BASE_URL}/api/v1/check?domain=example.com")

# ❌ Wrong - Incorrect header name
response = requests.get(
    f"{BASE_URL}/api/v1/check?domain=example.com",
    headers={"Authorization": f"Bearer {API_KEY}"}
)

# βœ… Correct
response = requests.get(
    f"{BASE_URL}/api/v1/check?domain=example.com",
    headers={"X-API-Key": API_KEY}
)

JavaScript:

// ❌ Wrong
fetch(url)  // No headers

// βœ… Correct
fetch(url, {
  headers: {
    'X-API-Key': API_KEY
  }
})

cURL:

# ❌ Wrong
curl "https://api.reputeapi.com/api/v1/check?domain=example.com"

# βœ… Correct
curl "https://api.reputeapi.com/api/v1/check?domain=example.com" \
  -H "X-API-Key: your-api-key"

Verification:

# Test your API key
import requests

API_KEY = "your-api-key-here"
BASE_URL = "https://api.reputeapi.com"

response = requests.get(
    f"{BASE_URL}/api/v1/usage",
    headers={"X-API-Key": API_KEY}
)

if response.status_code == 200:
    print("βœ… API key is valid")
    print(f"Your plan: {response.json()['plan']}")
else:
    print(f"❌ API key error: {response.status_code}")
    print(response.json())

Rate Limiting IssuesΒΆ

429 Too Many RequestsΒΆ

Symptoms:

{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Please try again later.",
  "retry_after": 60,
  "status": 429
}

Rate Limits by Tier:

Tier Per Minute Per Day
Free 10 1,000
Basic 60 10,000
Premium 120 50,000

Solutions:

1. Add Delay Between RequestsΒΆ

import time

domains = ["example1.com", "example2.com", "example3.com"]

for domain in domains:
    result = check_domain(domain)
    print(f"{domain}: {result['score']}/100")

    # Add 1 second delay to respect rate limits
    time.sleep(1)

2. Implement Retry Logic with Exponential BackoffΒΆ

import time
import requests

def check_domain_with_retry(domain: str, max_retries: int = 3):
    """Check domain with automatic retry on rate limit"""

    retries = 0
    delay = 1

    while retries < max_retries:
        try:
            response = requests.get(
                f"{BASE_URL}/api/v1/check",
                params={"domain": domain},
                headers={"X-API-Key": API_KEY},
                timeout=10
            )

            if response.status_code == 429:
                # Rate limited
                retry_after = int(response.headers.get('Retry-After', delay))
                print(f"Rate limited. Waiting {retry_after} seconds...")
                time.sleep(retry_after)
                retries += 1
                delay *= 2  # Exponential backoff
                continue

            response.raise_for_status()
            return response.json()

        except requests.exceptions.HTTPError as e:
            if e.response.status_code != 429:
                raise
            retries += 1

    raise Exception(f"Max retries ({max_retries}) exceeded")

# Usage
result = check_domain_with_retry("example.com")

3. Use Bulk Endpoint for Multiple DomainsΒΆ

# ❌ Bad - Multiple individual requests
for domain in domains:
    check_domain(domain)  # Will hit rate limit

# βœ… Good - Single bulk request
bulk_validate(domains)  # Validates all at once

4. Implement Request QueueΒΆ

import queue
import threading
import time

class RateLimitedQueue:
    """Queue with rate limiting"""

    def __init__(self, requests_per_minute: int = 10):
        self.queue = queue.Queue()
        self.requests_per_minute = requests_per_minute
        self.delay = 60.0 / requests_per_minute

    def add_domain(self, domain: str):
        """Add domain to queue"""
        self.queue.put(domain)

    def process_queue(self):
        """Process queue with rate limiting"""
        while not self.queue.empty():
            domain = self.queue.get()

            try:
                result = check_domain(domain)
                print(f"{domain}: {result['score']}/100")
            except Exception as e:
                print(f"Error for {domain}: {e}")

            # Rate limiting delay
            time.sleep(self.delay)

# Usage
rate_queue = RateLimitedQueue(requests_per_minute=10)

for domain in large_domain_list:
    rate_queue.add_domain(domain)

rate_queue.process_queue()

Request IssuesΒΆ

400 Bad Request - Invalid DomainΒΆ

Symptoms:

{
  "error": "Bad Request",
  "message": "Invalid domain format",
  "status": 400
}

Common Causes:

# ❌ Wrong - Including protocol
check_domain("https://example.com")

# ❌ Wrong - Including path
check_domain("example.com/page")

# ❌ Wrong - Including port
check_domain("example.com:443")

# ❌ Wrong - Email address
check_domain("user@example.com")

# βœ… Correct - Domain only
check_domain("example.com")

Solution - Domain Validation:

import re
from urllib.parse import urlparse

def validate_domain(input_string: str) -> str:
    """
    Validate and clean domain input

    Args:
        input_string: User input (might include protocol, path, etc.)

    Returns:
        Clean domain name

    Raises:
        ValueError: If domain is invalid
    """
    # Remove whitespace
    domain = input_string.strip()

    # Remove protocol if present
    if '://' in domain:
        domain = urlparse(domain).netloc

    # Remove path if present
    domain = domain.split('/')[0]

    # Remove port if present
    domain = domain.split(':')[0]

    # Extract domain from email if needed
    if '@' in domain:
        domain = domain.split('@')[1]

    # Validate domain format
    domain_pattern = r'^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$'

    if not re.match(domain_pattern, domain):
        raise ValueError(f"Invalid domain format: {domain}")

    return domain.lower()

# Usage
try:
    domain = validate_domain("https://example.com/path")
    print(f"Clean domain: {domain}")  # Output: example.com

    result = check_domain(domain)
except ValueError as e:
    print(f"Validation error: {e}")

Request TimeoutΒΆ

Symptoms:

requests.exceptions.Timeout: HTTPConnectionPool(host='api.reputeapi.com', port=443): Read timed out.

Solutions:

import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

def create_session_with_retries(timeout: int = 10):
    """Create session with timeouts and retries"""

    session = requests.Session()

    # Configure retry strategy
    retry_strategy = Retry(
        total=3,
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods=["GET", "POST"],
        backoff_factor=1  # Wait 1, 2, 4 seconds between retries
    )

    adapter = HTTPAdapter(max_retries=retry_strategy)
    session.mount("https://", adapter)
    session.mount("http://", adapter)

    return session

# Usage
session = create_session_with_retries(timeout=15)
session.headers.update({"X-API-Key": API_KEY})

try:
    response = session.get(
        f"{BASE_URL}/api/v1/check",
        params={"domain": "example.com"},
        timeout=15  # 15 second timeout
    )
    result = response.json()
except requests.exceptions.Timeout:
    print("Request timed out after 15 seconds")
except Exception as e:
    print(f"Error: {e}")

Response IssuesΒΆ

Unexpected Response FormatΒΆ

Symptoms:

KeyError: 'score'
# or
TypeError: 'NoneType' object is not subscriptable

Cause: Assuming response structure without validation

Solution - Safe Response Parsing:

def safe_get_score(domain: str) -> dict:
    """
    Safely get domain score with validation

    Returns:
        Dict with score and status, never raises exceptions
    """
    try:
        response = requests.get(
            f"{BASE_URL}/api/v1/check",
            params={"domain": domain},
            headers={"X-API-Key": API_KEY},
            timeout=10
        )

        # Check HTTP status
        if not response.ok:
            return {
                "domain": domain,
                "status": "error",
                "error": f"HTTP {response.status_code}",
                "score": None
            }

        # Parse JSON
        try:
            result = response.json()
        except ValueError:
            return {
                "domain": domain,
                "status": "error",
                "error": "Invalid JSON response",
                "score": None
            }

        # Validate response structure
        if not isinstance(result, dict):
            return {
                "domain": domain,
                "status": "error",
                "error": "Unexpected response format",
                "score": None
            }

        # Extract score safely
        score = result.get('score')
        if score is None:
            return {
                "domain": domain,
                "status": "error",
                "error": "Score not in response",
                "score": None
            }

        return {
            "domain": domain,
            "status": "success",
            "score": score,
            "grade": result.get('grade', 'Unknown'),
            "data": result
        }

    except requests.exceptions.RequestException as e:
        return {
            "domain": domain,
            "status": "error",
            "error": str(e),
            "score": None
        }

# Usage
result = safe_get_score("example.com")

if result["status"] == "success":
    print(f"Score: {result['score']}/100")
else:
    print(f"Error: {result['error']}")

DNS Resolution IssuesΒΆ

Domain Not FoundΒΆ

Symptoms:

{
  "error": "Domain not found",
  "message": "Unable to resolve DNS records for domain",
  "code": "DNS_RESOLUTION_FAILED"
}

Possible Causes:

  1. Domain doesn't exist
  2. DNS servers are unreachable
  3. Domain recently registered (DNS not propagated)
  4. Typo in domain name

Solutions:

import socket
import dns.resolver

def verify_domain_exists(domain: str) -> tuple[bool, str]:
    """
    Verify domain exists before API call

    Returns:
        Tuple of (exists, message)
    """
    try:
        # Try to resolve A record
        answers = dns.resolver.resolve(domain, 'A')
        return True, f"Domain exists with {len(answers)} A records"

    except dns.resolver.NXDOMAIN:
        return False, "Domain does not exist"

    except dns.resolver.NoAnswer:
        return False, "Domain exists but has no A records"

    except dns.resolver.Timeout:
        return False, "DNS query timed out"

    except Exception as e:
        return False, f"DNS error: {str(e)}"

# Usage
domain = "example.com"
exists, message = verify_domain_exists(domain)

if exists:
    print(f"βœ… {message}")
    result = check_domain(domain)
else:
    print(f"❌ {message}")
    print("Cannot validate domain that doesn't exist")

Connection IssuesΒΆ

SSL Certificate Verification FailedΒΆ

Symptoms:

requests.exceptions.SSLError: HTTPSConnectionPool(host='api.reputeapi.com', port=443): Max retries exceeded with url: ...

Causes: - Outdated SSL certificates on your system - Corporate firewall/proxy interfering - System clock incorrect

Solutions:

1. Update CA CertificatesΒΆ

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install ca-certificates

# macOS
brew install ca-certificates

# Python - Update certifi
pip install --upgrade certifi

2. Use System CertificatesΒΆ

import requests
import certifi

response = requests.get(
    f"{BASE_URL}/api/v1/check",
    params={"domain": "example.com"},
    headers={"X-API-Key": API_KEY},
    verify=certifi.where()  # Use certifi's CA bundle
)

3. For Corporate ProxiesΒΆ

import requests

proxies = {
    'http': 'http://proxy.company.com:8080',
    'https': 'http://proxy.company.com:8080',
}

response = requests.get(
    f"{BASE_URL}/api/v1/check",
    params={"domain": "example.com"},
    headers={"X-API-Key": API_KEY},
    proxies=proxies,
    verify='/path/to/corporate-ca-bundle.crt'
)

Performance IssuesΒΆ

Slow Response TimesΒΆ

Symptoms: Requests taking 10+ seconds

Solutions:

1. Use Score Endpoint for Quick ChecksΒΆ

# ❌ Slow - Full check with all details
response = requests.get(f"{BASE_URL}/api/v1/check?domain=example.com")
# Takes ~2-5 seconds

# βœ… Fast - Score only
response = requests.get(f"{BASE_URL}/api/v1/score?domain=example.com")
# Takes ~0.5-1 second

2. Enable CachingΒΆ

from functools import lru_cache
import time

@lru_cache(maxsize=128)
def check_domain_cached(domain: str) -> dict:
    """Check domain with local caching"""
    response = requests.get(
        f"{BASE_URL}/api/v1/check",
        params={"domain": domain},
        headers={"X-API-Key": API_KEY}
    )
    return response.json()

# First call - hits API
start = time.time()
result1 = check_domain_cached("example.com")
print(f"First call: {time.time() - start:.2f}s")

# Second call - from cache
start = time.time()
result2 = check_domain_cached("example.com")
print(f"Second call: {time.time() - start:.2f}s")

3. Use Async for Multiple DomainsΒΆ

import asyncio
import httpx

async def check_domains_async(domains: list) -> list:
    """Check multiple domains concurrently"""
    async with httpx.AsyncClient() as client:
        tasks = [
            client.get(
                f"{BASE_URL}/api/v1/check",
                params={"domain": domain},
                headers={"X-API-Key": API_KEY}
            )
            for domain in domains
        ]
        responses = await asyncio.gather(*tasks)
        return [r.json() for r in responses]

# Usage
domains = ["example1.com", "example2.com", "example3.com"]
results = asyncio.run(check_domains_async(domains))
# Much faster than sequential calls

Data IssuesΒΆ

Missing DKIM SelectorsΒΆ

Symptoms: DKIM validation fails even though DKIM is configured

Solution: Provide DKIM selectors explicitly

# ❌ Without selectors - may miss DKIM keys
result = requests.get(
    f"{BASE_URL}/api/v1/check",
    params={"domain": "example.com"},
    headers={"X-API-Key": API_KEY}
).json()

# βœ… With selectors - finds DKIM keys
result = requests.get(
    f"{BASE_URL}/api/v1/check",
    params={
        "domain": "example.com",
        "selectors": "default,google,k1,selector1"
    },
    headers={"X-API-Key": API_KEY}
).json()

Finding DKIM Selectors:

import dns.resolver

def find_common_selectors(domain: str) -> list:
    """Try common DKIM selectors"""

    common_selectors = [
        "default", "google", "k1", "k2", "k3",
        "selector1", "selector2", "dkim", "mail",
        "smtp", "email", "s1", "s2"
    ]

    found = []

    for selector in common_selectors:
        try:
            record_name = f"{selector}._domainkey.{domain}"
            answers = dns.resolver.resolve(record_name, 'TXT')
            if answers:
                found.append(selector)
                print(f"βœ“ Found: {selector}")
        except:
            pass

    return found

# Usage
selectors = find_common_selectors("example.com")
if selectors:
    print(f"\nFound selectors: {', '.join(selectors)}")
else:
    print("No common selectors found")

Debugging ChecklistΒΆ

When troubleshooting issues, check:

1. API KeyΒΆ

# Verify API key
print(f"API Key: {API_KEY[:10]}...")  # Don't print full key
print(f"Key length: {len(API_KEY)}")
print(f"Key starts with: {API_KEY[:3]}")

2. Network ConnectivityΒΆ

import requests

try:
    response = requests.get("https://api.reputeapi.com/health", timeout=5)
    print(f"βœ… API is reachable: {response.status_code}")
except Exception as e:
    print(f"❌ Cannot reach API: {e}")

3. Request DetailsΒΆ

import requests

# Enable debug logging
import logging
import http.client as http_client

http_client.HTTPConnection.debuglevel = 1
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

# Make request
response = requests.get(
    f"{BASE_URL}/api/v1/check",
    params={"domain": "example.com"},
    headers={"X-API-Key": API_KEY}
)

4. Response InspectionΒΆ

response = requests.get(url, headers=headers)

print(f"Status Code: {response.status_code}")
print(f"Headers: {dict(response.headers)}")
print(f"Response Time: {response.elapsed.total_seconds()}s")
print(f"Response Body: {response.text[:500]}")  # First 500 chars

Getting HelpΒΆ

Still stuck? Here's how to get help:

1. Check DocumentationΒΆ

2. Search FAQΒΆ

3. Contact SupportΒΆ

When contacting support, include:

import sys
import requests

# Diagnostic information
print("=== Diagnostic Information ===")
print(f"Python version: {sys.version}")
print(f"requests version: {requests.__version__}")
print(f"Operating System: {sys.platform}")
print(f"API endpoint: {BASE_URL}")
print(f"Domain being checked: example.com")
print(f"Error message: [paste error here]")
print(f"Full traceback: [paste traceback here]")

Send to: support@reputeapi.com


Additional ResourcesΒΆ