{"openapi":"3.0.3","info":{"title":"safety-lookup API","description":"API for safe URL redirect resolution and adult-domain classification.","version":"0.1.507"},"components":{"schemas":{}},"paths":{"/health":{"get":{"summary":"Health check","tags":["system"],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"api_version":{"type":"string"},"status":{"type":"string","enum":["ok"]},"checked_at":{"type":"string","format":"date-time"}},"required":["api_version","status","checked_at"]}}}}}}},"/v1/classify":{"get":{"summary":"Classify a URL with GET","tags":["classification"],"description":"GET variant for browser-based checks and raw JSON inspection.","parameters":[{"schema":{"type":"string","minLength":1},"in":"query","name":"url","required":true,"description":"URL to classify."},{"schema":{"type":"boolean","default":true},"in":"query","name":"resolve_redirects","required":false},{"schema":{"type":"boolean","default":false},"in":"query","name":"use_remote_classifier","required":false},{"schema":{"type":"boolean","default":false},"in":"query","name":"include_redirect_chain","required":false}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"api_version":{"type":"string"},"input_url":{"type":"string"},"final_url":{"type":"string"},"input_hostname":{"type":["null","string"]},"final_hostname":{"type":["null","string"]},"registered_domain":{"type":["null","string"]},"verdict":{"type":"string","enum":["blocked","allowed","unknown","error"]},"category":{"type":"string","enum":["adult","shock","mixed_adult","gambling","dating","proxy_or_bypass","unknown","error"]},"confidence":{"type":"string","enum":["low","medium","high"]},"matched_domain":{"type":["null","string"]},"match_type":{"type":"string","enum":["exact","parent_domain","none"]},"source":{"type":"string"},"resolution_status":{"type":"string","enum":["resolved","not_resolved","blocked_unsafe_redirect","too_many_redirects","redirect_loop","timeout","request_error"]},"redirect_chain":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"status":{"type":"integer"},"location":{"type":"string","format":"uri"}},"required":["url","status"]}},"warnings":{"type":"array","items":{"type":"string"}},"checked_at":{"type":"string","format":"date-time"}},"required":["input_url","api_version","final_url","input_hostname","final_hostname","registered_domain","verdict","category","confidence","resolution_status","warnings","checked_at"]}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"api_version":{"type":"string"},"input_url":{"type":"string"},"final_url":{"type":"string"},"input_hostname":{"type":["null","string"]},"final_hostname":{"type":["null","string"]},"registered_domain":{"type":["null","string"]},"verdict":{"type":"string","enum":["blocked","allowed","unknown","error"]},"category":{"type":"string","enum":["adult","shock","mixed_adult","gambling","dating","proxy_or_bypass","unknown","error"]},"confidence":{"type":"string","enum":["low","medium","high"]},"matched_domain":{"type":["null","string"]},"match_type":{"type":"string","enum":["exact","parent_domain","none"]},"source":{"type":"string"},"resolution_status":{"type":"string","enum":["resolved","not_resolved","blocked_unsafe_redirect","too_many_redirects","redirect_loop","timeout","request_error"]},"redirect_chain":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"status":{"type":"integer"},"location":{"type":"string","format":"uri"}},"required":["url","status"]}},"warnings":{"type":"array","items":{"type":"string"}},"checked_at":{"type":"string","format":"date-time"}},"required":["input_url","api_version","final_url","input_hostname","final_hostname","registered_domain","verdict","category","confidence","resolution_status","warnings","checked_at"]},{"type":"object","properties":{"api_version":{"type":"string"},"error":{"type":"string","enum":["invalid_request"]},"details":{"type":"object","additionalProperties":true}},"required":["api_version","error","details"]}]}}}}}},"post":{"summary":"Classify a URL","tags":["classification"],"description":"Normalizes a URL, optionally resolves redirects, and classifies the final hostname.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1,"description":"URL to classify."},"resolve_redirects":{"type":"boolean","default":true,"description":"Whether to resolve redirects before classification."},"use_remote_classifier":{"type":"boolean","default":false,"description":"Whether to use the optional remote classifier when local lookup is unknown."},"include_redirect_chain":{"type":"boolean","default":false,"description":"Whether to include the redirect chain in the response."}},"required":["url"]}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"api_version":{"type":"string"},"input_url":{"type":"string"},"final_url":{"type":"string"},"input_hostname":{"type":["null","string"]},"final_hostname":{"type":["null","string"]},"registered_domain":{"type":["null","string"]},"verdict":{"type":"string","enum":["blocked","allowed","unknown","error"]},"category":{"type":"string","enum":["adult","shock","mixed_adult","gambling","dating","proxy_or_bypass","unknown","error"]},"confidence":{"type":"string","enum":["low","medium","high"]},"matched_domain":{"type":["null","string"]},"match_type":{"type":"string","enum":["exact","parent_domain","none"]},"source":{"type":"string"},"resolution_status":{"type":"string","enum":["resolved","not_resolved","blocked_unsafe_redirect","too_many_redirects","redirect_loop","timeout","request_error"]},"redirect_chain":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"status":{"type":"integer"},"location":{"type":"string","format":"uri"}},"required":["url","status"]}},"warnings":{"type":"array","items":{"type":"string"}},"checked_at":{"type":"string","format":"date-time"}},"required":["input_url","api_version","final_url","input_hostname","final_hostname","registered_domain","verdict","category","confidence","resolution_status","warnings","checked_at"]}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"api_version":{"type":"string"},"input_url":{"type":"string"},"final_url":{"type":"string"},"input_hostname":{"type":["null","string"]},"final_hostname":{"type":["null","string"]},"registered_domain":{"type":["null","string"]},"verdict":{"type":"string","enum":["blocked","allowed","unknown","error"]},"category":{"type":"string","enum":["adult","shock","mixed_adult","gambling","dating","proxy_or_bypass","unknown","error"]},"confidence":{"type":"string","enum":["low","medium","high"]},"matched_domain":{"type":["null","string"]},"match_type":{"type":"string","enum":["exact","parent_domain","none"]},"source":{"type":"string"},"resolution_status":{"type":"string","enum":["resolved","not_resolved","blocked_unsafe_redirect","too_many_redirects","redirect_loop","timeout","request_error"]},"redirect_chain":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"status":{"type":"integer"},"location":{"type":"string","format":"uri"}},"required":["url","status"]}},"warnings":{"type":"array","items":{"type":"string"}},"checked_at":{"type":"string","format":"date-time"}},"required":["input_url","api_version","final_url","input_hostname","final_hostname","registered_domain","verdict","category","confidence","resolution_status","warnings","checked_at"]},{"type":"object","properties":{"api_version":{"type":"string"},"error":{"type":"string","enum":["invalid_request"]},"details":{"type":"object","additionalProperties":true}},"required":["api_version","error","details"]}]}}}}}}},"/v1/classify-hostname":{"post":{"summary":"Classify a hostname","tags":["classification"],"description":"Classifies a hostname directly without redirect resolution.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"hostname":{"type":"string","minLength":1,"description":"Hostname to classify."},"use_remote_classifier":{"type":"boolean","default":false,"description":"Whether to use the optional remote classifier when local lookup is unknown."}},"required":["hostname"]}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"api_version":{"type":"string"},"hostname":{"type":"string"},"registered_domain":{"type":["null","string"]},"verdict":{"type":"string","enum":["blocked","allowed","unknown","error"]},"category":{"type":"string","enum":["adult","shock","mixed_adult","gambling","dating","proxy_or_bypass","unknown","error"]},"confidence":{"type":"string","enum":["low","medium","high"]},"matched_domain":{"type":["null","string"]},"match_type":{"type":"string","enum":["exact","parent_domain","none"]},"source":{"type":"string"},"warnings":{"type":"array","items":{"type":"string"}},"checked_at":{"type":"string","format":"date-time"}},"required":["hostname","api_version","registered_domain","verdict","category","confidence","source","warnings","checked_at"]}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"api_version":{"type":"string"},"hostname":{"type":"string"},"registered_domain":{"type":["null","string"]},"verdict":{"type":"string","enum":["blocked","allowed","unknown","error"]},"category":{"type":"string","enum":["adult","shock","mixed_adult","gambling","dating","proxy_or_bypass","unknown","error"]},"confidence":{"type":"string","enum":["low","medium","high"]},"matched_domain":{"type":["null","string"]},"match_type":{"type":"string","enum":["exact","parent_domain","none"]},"source":{"type":"string"},"warnings":{"type":"array","items":{"type":"string"}},"checked_at":{"type":"string","format":"date-time"}},"required":["hostname","api_version","registered_domain","verdict","category","confidence","source","warnings","checked_at"]},{"type":"object","properties":{"api_version":{"type":"string"},"error":{"type":"string","enum":["invalid_request"]},"details":{"type":"object","additionalProperties":true}},"required":["api_version","error","details"]}]}}}}}}},"/v1/admin/refresh-lists":{"post":{"summary":"Refresh configured blocklists","tags":["admin"],"description":"Fetches all enabled blocklists, parses them, upserts domains into MongoDB, and clears classification cache.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"api_version":{"type":"string"},"status":{"type":"string"},"totals":{"type":"object","additionalProperties":true}},"required":["api_version","status","totals"]}}}}}}}},"servers":[{"url":"http://localhost:3003","description":"Local development server"}],"tags":[{"name":"classification","description":"URL and hostname classification endpoints"},{"name":"admin","description":"Administrative blocklist maintenance endpoints"},{"name":"system","description":"Service health and metadata endpoints"}]}