Response FormatΒΆ

Standard response format for all API endpoints.

OverviewΒΆ

All API responses follow a consistent structure, making it easy to parse and handle results programmatically.

Response TypesΒΆ

Success ResponsesΒΆ

All successful responses (HTTP 200-299) return JSON with endpoint-specific data and metadata.

Error ResponsesΒΆ

All error responses (HTTP 400-599) return a standardized error structure:

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": {}
  },
  "request_id": "req_abc123"
}

See Error Codes for complete error documentation.

Common Response FieldsΒΆ

These fields appear across multiple endpoints:

Field Type Always Present Description
domain string Yes Domain that was checked
score integer Yes* Mailflow Security Score (0-100)
meta object Yes Response metadata
timestamp string In meta ISO 8601 timestamp

*Not present in error responses

Metadata ObjectΒΆ

Every success response includes a meta object with performance and caching information:

{
  "meta": {
    "version": "1.0.0",
    "latency_ms": 450,
    "timestamp": "2025-10-21T10:30:00Z",
    "cached": false
  }
}

Metadata FieldsΒΆ

Field Type Description
version string API version used
latency_ms integer Request processing time in milliseconds
timestamp string When response was generated (ISO 8601)
cached boolean Whether result was served from cache

Endpoint Response FormatsΒΆ

GET /api/v1/checkΒΆ

Full validation response with detailed results:

{
  "domain": "example.com",
  "score": 75,
  "score_breakdown": {
    "current_score": 75,
    "max_score": 100,
    "total_deductions": 25,
    "potential_score_if_fixed": 90,
    "issues_by_severity": {
      "critical": 0,
      "high": 1,
      "medium": 2,
      "low": 1
    },
    "total_issues": 4
  },
  "spf": {
    "present": true,
    "record": "v=spf1 include:_spf.google.com ~all",
    "dns_lookups": 2,
    "flattening_needed": false,
    "syntax_ok": true,
    "qualifier": "~all",
    "issues": []
  },
  "dkim": {
    "discovered_selectors": ["google", "default"],
    "keys": [
      {
        "selector": "google",
        "present": true,
        "key_algo": "rsa",
        "key_bits": 2048,
        "revoked": false,
        "issues": []
      }
    ],
    "issues": []
  },
  "dmarc": {
    "present": true,
    "record": "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com",
    "policy": "quarantine",
    "subdomain_policy": "none",
    "aspf": "r",
    "adkim": "r",
    "pct": 100,
    "rua": ["mailto:dmarc@example.com"],
    "ruf": [],
    "issues": []
  },
  "alignment": {
    "spf_aligned": "pass",
    "dkim_aligned": "pass",
    "pass_likelihood": "high"
  },
  "issues": [
    {
      "code": "DMARC_POLICY_WEAK",
      "category": "dmarc",
      "severity": "high",
      "points_deducted": 10,
      "score_gain_if_fixed": 10,
      "title": "DMARC Policy Too Permissive",
      "description": "DMARC policy is set to 'quarantine' instead of 'reject'",
      "remediation": "Update DMARC policy from 'quarantine' to 'reject' for maximum protection",
      "dns_snippet": {
        "generic": "_dmarc.example.com. IN TXT \"v=DMARC1; p=reject; rua=mailto:dmarc@example.com\"",
        "route53": null
      }
    }
  ],
  "top_issues": [
    {
      "code": "DMARC_POLICY_WEAK",
      "category": "dmarc",
      "severity": "high",
      "points_deducted": 10,
      "score_gain_if_fixed": 10,
      "title": "DMARC Policy Too Permissive",
      "description": "DMARC policy is set to 'quarantine' instead of 'reject'",
      "remediation": "Update DMARC policy from 'quarantine' to 'reject' for maximum protection",
      "dns_snippet": {
        "generic": "_dmarc.example.com. IN TXT \"v=DMARC1; p=reject; rua=mailto:dmarc@example.com\"",
        "route53": null
      }
    }
  ],
  "meta": {
    "version": "1.0.0",
    "latency_ms": 450,
    "timestamp": "2025-10-21T10:30:00Z",
    "cached": false
  }
}

GET /api/v1/scoreΒΆ

Lightweight score response:

{
  "domain": "example.com",
  "score": 75,
  "score_breakdown": {
    "current_score": 75,
    "max_score": 100,
    "total_deductions": 25,
    "potential_score_if_fixed": 90,
    "issues_by_severity": {
      "critical": 0,
      "high": 1,
      "medium": 2,
      "low": 1
    },
    "total_issues": 4
  },
  "top_issues": [
    {
      "code": "DMARC_POLICY_WEAK",
      "category": "dmarc",
      "severity": "high",
      "points_deducted": 10,
      "score_gain_if_fixed": 10,
      "title": "DMARC Policy Too Permissive",
      "description": "DMARC policy is set to 'quarantine' instead of 'reject'",
      "remediation": "Update DMARC policy from 'quarantine' to 'reject' for maximum protection",
      "dns_snippet": {
        "generic": "_dmarc.example.com. IN TXT \"v=DMARC1; p=reject; rua=mailto:dmarc@example.com\"",
        "route53": null
      }
    }
  ],
  "meta": {
    "version": "1.0.0",
    "latency_ms": 180,
    "timestamp": "2025-10-21T10:30:00Z",
    "cached": true
  }
}

POST /api/v1/recommendationsΒΆ

Recommendations response:

{
  "domain": "example.com",
  "current_score": 75,
  "potential_score": 90,
  "recommendations": [
    {
      "priority": 1,
      "issue_code": "DMARC_POLICY_WEAK",
      "category": "dmarc",
      "severity": "high",
      "score_gain": 10,
      "action": "Update DMARC policy from 'quarantine' to 'reject' for maximum protection",
      "dns_snippet": {
        "generic": "_dmarc.example.com. IN TXT \"v=DMARC1; p=reject; rua=mailto:dmarc@example.com\"",
        "route53": null
      },
      "verification": "Run /api/v1/check?domain=example.com to verify the fix"
    },
    {
      "priority": 2,
      "issue_code": "SPF_SOFTFAIL",
      "category": "spf",
      "severity": "medium",
      "score_gain": 8,
      "action": "Change SPF qualifier from '~all' (softfail) to '-all' (hardfail)",
      "dns_snippet": {
        "generic": "example.com. IN TXT \"v=spf1 include:_spf.google.com -all\"",
        "route53": null
      },
      "verification": "Run /api/v1/check?domain=example.com to verify the fix"
    }
  ],
  "meta": {
    "version": "1.0.0",
    "latency_ms": 520,
    "timestamp": "2025-10-21T10:30:00Z",
    "cached": false
  }
}

GET /api/v1/historyΒΆ

Historical snapshots response:

{
  "domain": "example.com",
  "snapshots": [
    {
      "timestamp": "2025-10-21T10:30:00Z",
      "score": 75,
      "spf_present": true,
      "dkim_present": true,
      "dmarc_present": true,
      "dmarc_policy": "quarantine",
      "critical_issues": 0,
      "high_issues": 1
    },
    {
      "timestamp": "2025-10-20T10:30:00Z",
      "score": 65,
      "spf_present": true,
      "dkim_present": false,
      "dmarc_present": true,
      "dmarc_policy": "none",
      "critical_issues": 1,
      "high_issues": 2
    }
  ],
  "total_snapshots": 45,
  "date_range": {
    "first": "2025-09-15T10:30:00Z",
    "last": "2025-10-21T10:30:00Z"
  },
  "meta": {
    "version": "1.0.0",
    "latency_ms": 120,
    "timestamp": "2025-10-21T10:30:00Z",
    "cached": false
  }
}

Nested Object SchemasΒΆ

Score Breakdown ObjectΒΆ

{
  "current_score": 75,
  "max_score": 100,
  "total_deductions": 25,
  "potential_score_if_fixed": 90,
  "issues_by_severity": {
    "critical": 0,
    "high": 1,
    "medium": 2,
    "low": 1,
    "info": 0
  },
  "total_issues": 4
}

Fields:

Field Type Description
current_score integer Current Mailflow Security Score (0-100)
max_score integer Maximum possible score (always 100)
total_deductions integer Total points deducted from max score
potential_score_if_fixed integer Score if all issues are resolved
issues_by_severity object Count of issues by severity level
total_issues integer Total number of issues found

SPF Result ObjectΒΆ

{
  "present": true,
  "record": "v=spf1 include:_spf.google.com ~all",
  "dns_lookups": 2,
  "flattening_needed": false,
  "syntax_ok": true,
  "qualifier": "~all",
  "issues": []
}

Fields:

Field Type Description
present boolean Whether SPF record exists
record string Raw SPF record (null if not present)
dns_lookups integer Number of DNS lookups required (max 10)
flattening_needed boolean Whether SPF flattening is recommended
syntax_ok boolean Whether SPF syntax is valid
qualifier string Final SPF qualifier (+all, -all, ~all, ?all)
issues array List of SPF-specific issues

DKIM Result ObjectΒΆ

{
  "discovered_selectors": ["google", "default"],
  "keys": [
    {
      "selector": "google",
      "present": true,
      "key_algo": "rsa",
      "key_bits": 2048,
      "revoked": false,
      "issues": []
    }
  ],
  "issues": []
}

Fields:

Field Type Description
discovered_selectors array DKIM selectors found via BIMI/discovery
keys array Validation results for each DKIM key
issues array General DKIM issues

DKIM Key Fields:

Field Type Description
selector string DKIM selector name
present boolean Whether DKIM key exists
key_algo string Key algorithm (rsa/ed25519)
key_bits integer Key length in bits
revoked boolean Whether key is revoked
issues array Issues specific to this key

DMARC Result ObjectΒΆ

{
  "present": true,
  "record": "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com",
  "policy": "quarantine",
  "subdomain_policy": "none",
  "aspf": "r",
  "adkim": "r",
  "pct": 100,
  "rua": ["mailto:dmarc@example.com"],
  "ruf": [],
  "issues": []
}

Fields:

Field Type Description
present boolean Whether DMARC record exists
record string Raw DMARC record (null if not present)
policy string DMARC policy: none, quarantine, or reject
subdomain_policy string Subdomain policy (sp tag)
aspf string SPF alignment mode: r (relaxed) or s (strict)
adkim string DKIM alignment mode: r (relaxed) or s (strict)
pct integer Percentage of messages to filter (0-100)
rua array Aggregate report URIs
ruf array Forensic report URIs
issues array DMARC-specific issues

Security Issue ObjectΒΆ

{
  "code": "DMARC_POLICY_WEAK",
  "category": "dmarc",
  "severity": "high",
  "points_deducted": 10,
  "score_gain_if_fixed": 10,
  "title": "DMARC Policy Too Permissive",
  "description": "DMARC policy is set to 'quarantine' instead of 'reject'",
  "remediation": "Update DMARC policy from 'quarantine' to 'reject' for maximum protection",
  "dns_snippet": {
    "generic": "_dmarc.example.com. IN TXT \"v=DMARC1; p=reject; rua=mailto:dmarc@example.com\"",
    "route53": null
  }
}

Fields:

Field Type Description
code string Unique issue code (e.g., DMARC_POLICY_WEAK)
category string Issue category: spf, dkim, dmarc, or dns
severity string Severity: critical, high, medium, low, or info
points_deducted integer Points deducted from score
score_gain_if_fixed integer Points gained if issue is resolved
title string Short issue title
description string Detailed issue description
remediation string Step-by-step fix instructions
dns_snippet object DNS configuration to fix the issue

DNS Snippet ObjectΒΆ

{
  "generic": "_dmarc.example.com. IN TXT \"v=DMARC1; p=reject; rua=mailto:dmarc@example.com\"",
  "route53": null
}

Fields:

Field Type Description
generic string BIND-style DNS record (universal format)
route53 string AWS Route53 JSON snippet (when applicable)

Alignment Result ObjectΒΆ

{
  "spf_aligned": "pass",
  "dkim_aligned": "pass",
  "pass_likelihood": "high"
}

Fields:

Field Type Description
spf_aligned string SPF alignment status: pass, fail, or unknown
dkim_aligned string DKIM alignment status: pass, fail, or unknown
pass_likelihood string DMARC pass likelihood: high, medium, or low

PaginationΒΆ

For endpoints that return lists (like /api/v1/history), pagination is handled via query parameters:

Query Parameters:

Parameter Type Default Description
limit integer 30 Number of items to return (max varies by endpoint)
offset integer 0 Number of items to skip

Response includes:

{
  "items": [...],
  "total": 150,
  "limit": 30,
  "offset": 0,
  "has_more": true
}

CachingΒΆ

Responses include caching information in the meta object:

{
  "meta": {
    "cached": true,
    "timestamp": "2025-10-21T10:30:00Z"
  }
}

Cache Behavior:

  • Results are cached for 15 minutes by default
  • Use ?refresh=true to bypass cache
  • Check meta.cached to see if result was served from cache
  • Cached results are still accurate but may not reflect very recent DNS changes

Cache Headers:

Cache-Control: public, max-age=900
ETag: "abc123def456"
Last-Modified: Mon, 21 Oct 2025 10:30:00 GMT

Response TimesΒΆ

Expected latency by endpoint:

Endpoint Cached Uncached Notes
/api/v1/check 100-200ms 400-700ms Full validation with DNS queries
/api/v1/score 50-100ms 150-300ms Lightweight, faster than /check
/api/v1/recommendations 150-250ms 500-800ms Includes validation + recommendation logic
/api/v1/history 50-150ms N/A Database query, no DNS lookups

Parsing ExamplesΒΆ

PythonΒΆ

import requests

response = requests.get(
    "https://api.reputeapi.com/api/v1/check",
    params={"domain": "example.com"},
    headers={"X-API-Key": "your-api-key"}
)

if response.status_code == 200:
    data = response.json()

    # Access common fields
    domain = data['domain']
    score = data['score']
    cached = data['meta']['cached']
    latency = data['meta']['latency_ms']

    # Access nested data
    spf_present = data['spf']['present']
    dmarc_policy = data['dmarc']['policy']

    # Iterate issues
    for issue in data['issues']:
        print(f"[{issue['severity']}] {issue['title']}")
        print(f"  Fix: {issue['remediation']}")
        if issue['dns_snippet']:
            print(f"  DNS: {issue['dns_snippet']['generic']}")

else:
    error = response.json()
    print(f"Error: {error['error']['code']}")
    print(f"Message: {error['error']['message']}")

JavaScriptΒΆ

const response = await fetch(
  'https://api.reputeapi.com/api/v1/check?domain=example.com',
  {
    headers: { 'X-API-Key': 'your-api-key' }
  }
);

if (response.ok) {
  const data = await response.json();

  // Access common fields
  const { domain, score, meta } = data;
  console.log(`${domain}: ${score}/100`);
  console.log(`Cached: ${meta.cached}, Latency: ${meta.latency_ms}ms`);

  // Access nested data
  const { spf, dkim, dmarc } = data;
  console.log(`SPF: ${spf.present ? 'Present' : 'Missing'}`);
  console.log(`DMARC Policy: ${dmarc.policy || 'None'}`);

  // Iterate issues
  data.issues.forEach(issue => {
    console.log(`[${issue.severity}] ${issue.title}`);
  });

} else {
  const error = await response.json();
  console.error(`Error ${error.error.code}: ${error.error.message}`);
}

Best PracticesΒΆ

1. Always Check HTTP StatusΒΆ

if response.status_code == 200:
    # Success path
    data = response.json()
else:
    # Error path
    error = response.json()

2. Use Type Hints (Python)ΒΆ

from typing import Dict, Any

def process_check_response(data: Dict[str, Any]) -> None:
    domain: str = data['domain']
    score: int = data['score']
    meta: Dict[str, Any] = data['meta']

3. Handle Optional FieldsΒΆ

# Some fields may be null
dmarc_policy = data['dmarc'].get('policy', 'none')
dns_snippet = issue.get('dns_snippet', {}).get('generic')

if dns_snippet:
    print(f"Apply this DNS record: {dns_snippet}")

4. Leverage MetadataΒΆ

# Check if result is cached
if data['meta']['cached']:
    print("Result served from cache")

# Monitor performance
latency = data['meta']['latency_ms']
if latency > 1000:
    print(f"Slow response: {latency}ms")