v1 API

API Reference

The MFA Feed API provides programmatic access to our made-for-advertising domain intelligence. Integrate MFA detection into your ad-tech stack, brand safety tools, or custom workflows.

Base URLhttps://mfa.redvolcano.uk/api/v1

Authentication

All API requests require an API key. Create and manage keys from the API Keys page in your dashboard.

Never share your API key publicly. If compromised, revoke it immediately from the API Keys page and create a new one.

  • Precedence: if both are present, the Authorization header wins — the ?api_key= query param is ignored even if the header is malformed.
  • Case: the Bearer scheme is matched case-insensitively (bearer, BEARER, etc. all work).
  • Caching: all responses carry Cache-Control: private, no-store. Safe to use with ?api_key= since intermediaries will not retain the body.
  • Duplicate params: repeating a query key (e.g. ?tier=red&tier=amber) returns 400 — we do not pick one silently.
  • Methods: only GET, HEAD, and OPTIONS are accepted. Other verbs return 405 with an Allow header.
httpBearer Token (recommended)
GET /api/v1/feed HTTP/1.1
Host: mfa.redvolcano.uk
Authorization: Bearer mfa_your_api_key_here
httpQuery Parameter
GET /api/v1/feed?api_key=mfa_your_api_key_here

Rate Limits

Rate limit headers are returned on every response from a valid API key (including 404 and 429). 401 responses omit them because there is no authenticated key to identify a bucket.

X-RateLimit-LimitMax requests per hour
X-RateLimit-RemainingRemaining in current window
X-RateLimit-ResetUnix timestamp of window reset
httpResponse Headers
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 100000
X-RateLimit-Remaining: 99847
X-RateLimit-Reset: 1712700000

Endpoints

GET/api/v1/feed

Returns a paginated list of MFA-flagged domains with scores, tiers, and detection signals. Invalid query values return 400 rather than being silently clamped or ignored — the response body lists each field that failed validation.

Parameters

pageinteger

Page number, min 1 (default: 1)

limitinteger

Results per page, 1–100 (default: 50). Values outside this range return 400.

tierstring

Filter by tier: red, amber, yellow

searchstring

Substring match on domain, max 100 chars

sortstring

Sort by: score, domain, created_at (default: score)

orderstring

Sort order: asc, desc (default: desc)

curlRequest
curl "https://mfa.redvolcano.uk/api/v1/feed?tier=red&limit=10" \
  -H "Authorization: Bearer mfa_your_key_here"
jsonResponse
{
  "domains": [
    {
      "id": 1,
      "domain": "example-mfa.com",
      "score": 87,
      "tier": "red",
      "created_at": "2026-03-15T10:30:00Z",
      "breakdown": [
        { "key": "ads_txt", "label": "Monetization",
          "score": 22, "max": 25 }
      ],
      "signals": [
        { "key": "excessive_ads", "label": "Excessive Ads" }
      ]
    }
  ],
  "total": 1523,
  "page": 1,
  "totalPages": 31,
  "isLimited": false,
  "totalAvailable": 1523
}
GET/api/v1/stats

Returns aggregate statistics about the MFA domain feed — total count and breakdown by tier.

curlRequest
curl "https://mfa.redvolcano.uk/api/v1/stats" \
  -H "Authorization: Bearer mfa_your_key_here"
jsonResponse
{
  "total": 10103,
  "red": 69,
  "amber": 1913,
  "yellow": 8121
}
GET/api/v1/domain/:domain

Look up a specific domain. Returns the full detection record if found, or 404 if the domain is not in the feed.

Parameters

domainstringrequired

The domain to look up (path parameter)

curlRequest
curl "https://mfa.redvolcano.uk/api/v1/domain/example-mfa.com" \
  -H "Authorization: Bearer mfa_your_key_here"
jsonResponse
{
  "domain": "example-mfa.com",
  "score": 87,
  "tier": "red",
  "created_at": "2026-03-15T10:30:00Z",
  "breakdown": [
    { "key": "ads_txt", "label": "Monetization",
      "score": 22, "max": 25 },
    { "key": "content", "label": "Content",
      "score": 18, "max": 20 }
  ],
  "signals": [
    { "key": "excessive_ads", "label": "Excessive Ads" },
    { "key": "thin_content", "label": "Thin Content" }
  ]
}
GET/api/v1/rings

Returns MFA ring data — clusters of domains sharing identical ads.txt configurations, indicating coordinated MFA networks. Only hashes with 5 or more domains are returned, sorted by size descending.

curlRequest
curl "https://mfa.redvolcano.uk/api/v1/rings" \
  -H "Authorization: Bearer mfa_your_key_here"
jsonResponse
{
  "rings": [
    {
      "hash": "a1b2c3d4e5f6",
      "size": 12,
      "domains": [
        {
          "domain": "site-a.com",
          "tier": "red",
          "score": 87,
          "created_at": "2026-03-27T20:39:01Z"
        }
      ],
      "tiers": { "red": 4, "amber": 6, "yellow": 2 }
    }
  ],
  "totalRings": 82,
  "totalDomainsInRings": 1532
}
GET/api/v1/feed/export

Export up to 50,000 matching domains as JSON (default) or CSV. Subject to a separate daily export quota.

Parameters

formatstring

Export format: json or csv (default: json)

tierstring

Filter by tier: red, amber, yellow

curlRequest
# Default — JSON array of domain records
curl "https://mfa.redvolcano.uk/api/v1/feed/export?tier=red" \
  -H "Authorization: Bearer mfa_your_key_here"

# CSV download
curl "https://mfa.redvolcano.uk/api/v1/feed/export?format=csv" \
  -H "Authorization: Bearer mfa_your_key_here" \
  -o mfa-feed.csv
jsonResponse
[
  {
    "id": 1,
    "domain": "example-mfa.com",
    "score": 87,
    "tier": "red",
    "created_at": "2026-03-15T10:30:00Z",
    "breakdown": [
      { "key": "ads_txt", "label": "Monetization",
        "score": 22, "max": 25 }
    ],
    "signals": [
      { "key": "excessive_ads", "label": "Excessive Ads" }
    ]
  }
]

CSV format (when ?format=csv)

Signals are joined with ; and wrapped in double quotes. The response carries Content-Type: text/csv and a filename disposition header so browsers download it.

csvCSV response body
domain,score,tier,detected_at,signals
example-mfa.com,87,red,2026-03-15T10:30:00Z,"Excessive Ads;Thin Content"
another-site.com,72,amber,2026-03-16T08:14:22Z,"Low Content Ratio"

Code Examples

pythonPython
import requests

API_KEY = "mfa_your_key_here"
BASE = "https://mfa.redvolcano.uk/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Get red-tier domains
resp = requests.get(f"{BASE}/feed", headers=headers,
                    params={"tier": "red", "limit": 100})
data = resp.json()

for d in data["domains"]:
    print(f"{d['domain']} — Score: {d['score']} ({d['tier']})")

# Check a specific domain
resp = requests.get(f"{BASE}/domain/example.com", headers=headers)
if resp.status_code == 200:
    print("Found:", resp.json())
elif resp.status_code == 404:
    print("Not in MFA feed")
javascriptJavaScript / Node.js
const API_KEY = "mfa_your_key_here";
const BASE = "https://mfa.redvolcano.uk/api/v1";
const headers = { Authorization: `Bearer ${API_KEY}` };

// Get feed with filters
const res = await fetch(`${BASE}/feed?tier=red&limit=50`, { headers });
const data = await res.json();
console.log(`Found ${data.total} domains`);

// Export full feed as JSON
const exportRes = await fetch(`${BASE}/feed/export`, { headers });
const allDomains = await exportRes.json();

Error Codes

CodeMeaningDescription
400Bad RequestA query parameter failed validation. Body includes a details array with the failing field(s).
401UnauthorizedMissing or invalid API key
403ForbiddenAPI access not available for your account
404Not FoundThe requested domain was not found in the feed
405Method Not AllowedOnly GET/HEAD/OPTIONS are supported. The response includes an Allow header.
429Too Many RequestsRate limit exceeded — check X-RateLimit-Reset header
500Server ErrorInternal error. Please try again later

All errors return a JSON body with an error field.

MFA Feed API v1 — Powered by Red Volcano