{
  "openapi": "3.1.0",
  "info": {
    "title": "Sentinel Fraud Detection API",
    "version": "1.0.0",
    "description": "Real-time fraud, VPN, residential-proxy, datacenter, antidetect-browser, and bot detection. Sub-40ms global response. Free tier: 1,000 requests per hour, no credit card.",
    "contact": {
      "name": "Sentinel Support",
      "email": "support@sntlhq.com",
      "url": "https://sntlhq.com/contact"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://sntlhq.com/terms"
    },
    "termsOfService": "https://sntlhq.com/terms"
  },
  "externalDocs": {
    "description": "Full developer documentation",
    "url": "https://sntlhq.com/api"
  },
  "servers": [
    { "url": "https://sntlhq.com", "description": "Production" }
  ],
  "security": [
    { "bearerAuth": [] }
  ],
  "tags": [
    { "name": "Evaluate", "description": "Score visitor sessions for fraud signals." },
    { "name": "Sandbox", "description": "Public, unauthenticated sample responses for development." },
    { "name": "Status", "description": "Service health and aggregate threat feed." }
  ],
  "paths": {
    "/v1/evaluate": {
      "post": {
        "summary": "Evaluate a visitor session",
        "description": "Forward the client-side Sentinel token (auto-injected by the SDK into your forms) to receive a structured threat assessment: decision, risk_score, network signals, and device signals.",
        "operationId": "evaluate",
        "tags": ["Evaluate"],
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/EvaluateRequest" },
              "examples": {
                "minimal": {
                  "summary": "Minimal request",
                  "value": { "token": "mcl_eyJhbGciOi..." }
                },
                "withFingerprint": {
                  "summary": "Request with optional Fingerprint event ID",
                  "value": { "token": "mcl_eyJhbGciOi...", "fingerprintEventId": "fp_event_a8c..." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Evaluation succeeded",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/EvaluateResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/evaluate/sample": {
      "get": {
        "summary": "Sample evaluation response",
        "description": "Public, unauthenticated, rate-limited (30 req/min per IP). Returns a deterministic example /v1/evaluate response in one of three preset scenarios so you can wire your parsing logic without signing up.",
        "operationId": "evaluateSample",
        "tags": ["Sandbox"],
        "security": [],
        "parameters": [
          {
            "name": "scenario",
            "in": "query",
            "required": false,
            "description": "Which preset scenario to return.",
            "schema": {
              "type": "string",
              "enum": ["clean", "vpn", "datacenter"],
              "default": "vpn"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sample evaluation",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/EvaluateResponse" }
              }
            }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/status": {
      "get": {
        "summary": "Service health",
        "operationId": "status",
        "tags": ["Status"],
        "security": [],
        "responses": {
          "200": {
            "description": "Status payload",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string", "example": "operational" },
                    "uptime_pct_30d": { "type": "number", "example": 99.98 }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/threat-feed": {
      "get": {
        "summary": "Aggregate threat counts",
        "description": "Public, anonymized aggregate counts: threats blocked in the last 24h, weekly identity checks, and developer count. Used to power the homepage trust strip.",
        "operationId": "threatFeed",
        "tags": ["Status"],
        "security": [],
        "responses": {
          "200": {
            "description": "Aggregate counts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "today": {
                      "type": "object",
                      "properties": {
                        "total": { "type": "integer" },
                        "threats": { "type": "integer" },
                        "vpn": { "type": "integer" },
                        "proxy": { "type": "integer" },
                        "dch": { "type": "integer" }
                      }
                    },
                    "week_total": { "type": "integer" },
                    "total_users": { "type": "integer" }
                  }
                }
              }
            }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk_live_...",
        "description": "Pass your Sentinel API key from https://sntlhq.com/dashboard as a Bearer token. Keys start with sk_live_."
      }
    },
    "schemas": {
      "EvaluateRequest": {
        "type": "object",
        "required": ["token"],
        "properties": {
          "token": {
            "type": "string",
            "description": "Client-side token captured from the Sentinel SDK (auto-injected as a hidden input named 'monocle' on any form with class 'monocle-enriched').",
            "example": "mcl_eyJhbGciOi..."
          },
          "fingerprintEventId": {
            "type": "string",
            "description": "Optional Fingerprint event id for additional device signals.",
            "example": "fp_event_a8c..."
          }
        }
      },
      "EvaluateResponse": {
        "type": "object",
        "properties": {
          "decision": {
            "type": "string",
            "enum": ["allow", "review", "block"],
            "description": "Recommended action."
          },
          "risk_score": { "type": "integer", "minimum": 0, "maximum": 100, "example": 71 },
          "ip": { "type": "string", "example": "198.51.100.18" },
          "country": { "type": "string", "example": "NL", "description": "ISO-2 country code." },
          "asn": { "type": "string", "example": "AS9009" },
          "asn_org": { "type": "string", "example": "M247 Europe SRL" },
          "network": {
            "type": "object",
            "properties": {
              "vpn": { "type": "boolean" },
              "proxy": { "type": "boolean" },
              "datacenter": { "type": "boolean" },
              "anonymous": { "type": "boolean" },
              "residential": { "type": "boolean" }
            }
          },
          "device": {
            "type": "object",
            "properties": {
              "headless": { "type": "boolean" },
              "automation": { "type": "boolean" },
              "fingerprint_age_days": { "type": "integer" }
            }
          },
          "reasons": {
            "type": "array",
            "items": { "type": "string" },
            "example": ["ip_in_known_vpn_range", "datacenter_asn", "fingerprint_age_under_24h"]
          },
          "evaluated_in_ms": { "type": "integer", "example": 28 }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string", "example": "Invalid token" }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request body",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "RateLimited": {
        "description": "Too many requests",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": { "type": "integer" }
          }
        },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    }
  }
}
