Building a fraud detection pipeline
A single suspicious signal rarely tells the full story. An email might look fine on its own, but paired with a datacenter IP and a freshly registered domain, the picture changes fast. Combining multiple Veille APIs into a pipeline gives you a composite risk view of every signup.
Architecture overview
At its simplest: validate the email (/v1/intelligence/email), check the domain age (/v1/intelligence/domain), and score the IP (/v1/intelligence/ip). Three calls, three signals, one composite score.
Quick integration
Python
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.veille.io/v1"
def score_signup(email: str, ip: str) -> dict:
headers = {"x-api-key": API_KEY}
email_data = requests.get(
f"{BASE_URL}/intelligence/email", params={"query": email}, headers=headers
).json()
domain_data = requests.get(
f"{BASE_URL}/intelligence/domain", params={"query": email_data["domain"]}, headers=headers
).json()
ip_data = requests.get(
f"{BASE_URL}/intelligence/ip", params={"query": ip}, headers=headers
).json()
age = min(domain_data.get("domain_age_days", 365), 365)
domain_risk = ((365 - age) / 365) * 100
composite = (
email_data["risk_score"] * 0.40
+ domain_risk * 0.35
+ ip_data["threat_score"] * 0.25
)
return {
"composite_score": round(composite),
"disposable_email": email_data["disposable"],
"vpn_or_proxy": ip_data["is_vpn"] or ip_data["is_proxy"],
"domain_age_days": domain_data.get("domain_age_days"),
}
TypeScript
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://api.veille.io/v1";
const headers = { "x-api-key": API_KEY };
async function scoreSignup(email: string, ip: string) {
const [emailResponse, ipResponse] = await Promise.all([
fetch(`${BASE_URL}/intelligence/email?query=${email}`, { headers }),
fetch(`${BASE_URL}/intelligence/ip?query=${ip}`, { headers }),
]);
const [emailData, ipData] = await Promise.all([
emailResponse.json(),
ipResponse.json(),
]);
const domainResponse = await fetch(
`${BASE_URL}/intelligence/domain?query=${emailData.domain}`,
{ headers }
);
const domainData = await domainResponse.json();
const age = Math.min(domainData.domain_age_days ?? 365, 365);
const domainRisk = ((365 - age) / 365) * 100;
return {
compositeScore: Math.round(
emailData.risk_score * 0.4 + domainRisk * 0.35 + ipData.threat_score * 0.25
),
disposableEmail: emailData.disposable,
vpnOrProxy: ipData.is_vpn || ipData.is_proxy,
domainAgeDays: domainData.domain_age_days,
};
}
Recommended weights
| Signal | Weight | Why |
|---|---|---|
| Email risk score | 40% | Disposable/role accounts are the strongest fraud indicator |
| Domain age risk | 35% | Newly registered domains correlate heavily with fraud |
| IP threat score | 25% | VPNs are also used by legitimate privacy-conscious users |
5 use cases
- User registration - compute a composite score at signup and auto-reject above a threshold.
- Checkout verification - run the pipeline before processing a payment to catch synthetic identities.
- Marketplace seller onboarding - screen new merchants by combining email, domain, and IP signals.
- Content moderation - prioritize review for posts from high-risk accounts.
- Webhook security - validate the origin IP and domain of incoming webhooks before processing them.