{"openapi":"3.0.3","info":{"title":"Signup Fraud & Trust Scorer API","version":"1.0.0","description":"Evaluates signup risk from email, IP, and User-Agent inputs using disposable-domain detection, MX lookup, plus-alias/role heuristics, IP checks, and bot classification."},"servers":[{"url":"https://api.tinplate.dev","description":"Production Edge Gateway"}],"components":{"schemas":{"SignupFraudResponse":{"type":"object","properties":{"trust_score":{"type":"integer","minimum":0,"maximum":100,"example":90},"risk_level":{"type":"string","enum":["low","medium","high"],"example":"low"},"verdict":{"type":"string","enum":["allow","challenge","block"],"example":"allow"},"email_analysis":{"type":"object","properties":{"valid_syntax":{"type":"boolean"},"domain":{"type":"string","nullable":true},"is_disposable":{"type":"boolean"},"is_free_provider":{"type":"boolean"},"is_role_address":{"type":"boolean"},"has_plus_alias":{"type":"boolean"},"has_mx":{"type":"boolean","nullable":true}},"required":["valid_syntax","domain","is_disposable","is_free_provider","is_role_address","has_plus_alias","has_mx"]},"ip_analysis":{"type":"object","nullable":true,"properties":{"ip":{"type":"string"},"is_private_or_bogon":{"type":"boolean"},"is_datacenter":{"type":"boolean"},"asn_org":{"type":"string","nullable":true}},"required":["ip","is_private_or_bogon","is_datacenter","asn_org"]},"ua_analysis":{"type":"object","nullable":true,"properties":{"is_bot":{"type":"boolean"},"category":{"type":"string"}},"required":["is_bot","category"]},"signals":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"severity":{"type":"string","enum":["info","low","medium","high"]},"delta":{"type":"integer"},"detail":{"type":"string"}},"required":["id","severity","delta","detail"]}}},"required":["trust_score","risk_level","verdict","email_analysis","ip_analysis","ua_analysis","signals"]},"SignupFraudRequest":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320,"example":"alice@tinplate.dev","description":"Signup email address to evaluate."},"ip":{"type":"string","maxLength":64,"example":"8.8.8.8","description":"End-user IPv4/IPv6 address (explicit input; never inferred from request.cf)."},"user_agent":{"type":"string","maxLength":2048,"example":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/130.0.0.0 Safari/537.36","description":"End-user HTTP User-Agent string."},"check_mx":{"type":"boolean","example":true,"description":"Verify domain MX records via DNS-over-HTTPS (default true)."}},"required":["email"]},"ResponseMeta":{"type":"object","required":["request_id"],"properties":{"request_id":{"type":"string","format":"uuid"},"ms":{"type":"integer","minimum":0},"version":{"type":"string","example":"1.0.0"}}},"ErrorEnvelope":{"type":"object","required":["ok","error","meta"],"properties":{"ok":{"type":"boolean","enum":[false]},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"invalid_input"},"message":{"type":"string","example":"Request body failed validation"}}},"meta":{"$ref":"#/components/schemas/ResponseMeta"}}}},"parameters":{}},"paths":{"/v1/signup-fraud":{"post":{"tags":["02_SIGNUP_FRAUD"],"summary":"Score a signup event for fraud and abuse risk","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupFraudRequest"}}}},"responses":{"200":{"description":"Trust score, verdict, and transparent signal breakdown","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/SignupFraudResponse"},"meta":{"$ref":"#/components/schemas/ResponseMeta"}},"required":["ok","data","meta"]}}}},"400":{"description":"Invalid input or malformed JSON request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Missing or invalid authentication credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"Request payload exceeds subscribed plan byte cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}}}