{
  "openapi": "3.1.0",
  "info": {
    "title": "Beezifi Security API",
    "version": "1.0.0",
    "description": "Beezifi Security is a multi-tenant Security Decision Engine. Your application sends a lightweight JSON payload to /api/v1/check before processing any request. Beezifi evaluates your active rules in priority order and responds in milliseconds with a decision (ALLOW, BLOCK, or REDIRECT) your app can act on. No traffic proxying — Beezifi never sits in front of your traffic."
  },
  "servers": [
    { "url": "https://your-domain.com", "description": "Production" }
  ],
  "paths": {
    "/api/v1/check": {
      "post": {
        "operationId": "checkRequest",
        "summary": "Evaluate a request against your security rules",
        "description": "The single endpoint your application calls before handling any incoming request. Rules are evaluated in priority order (lowest number first). The first matching rule stops evaluation and returns its decision. If no rules match, the tenant's Default Policy is applied.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CheckRequest" },
              "example": {
                "apiKey": "bzf_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6",
                "ip": "1.2.3.4",
                "country": "US",
                "path": "/login",
                "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
                "lat": 37.7749,
                "lng": -122.4194,
                "timestamp": 1715123456789
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rule evaluation complete. Always HTTP 200 regardless of the security decision — inspect the `decision` field.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CheckResponse" },
                "examples": {
                  "allow": {
                    "summary": "Request allowed",
                    "value": { "decision": "ALLOW", "reason": "All checks passed" }
                  },
                  "block": {
                    "summary": "Request blocked (ghost response)",
                    "value": {
                      "decision": "BLOCK",
                      "reason": "Country RU is blocked",
                      "actionPayload": {
                        "type": "html",
                        "value": "<!DOCTYPE html><html><body><h1>Access Restricted</h1></body></html>"
                      }
                    }
                  },
                  "redirect": {
                    "summary": "Request redirected (ghost response)",
                    "value": {
                      "decision": "REDIRECT",
                      "reason": "Request outside allowed geofence (342 km from center)",
                      "actionPayload": {
                        "type": "url",
                        "value": "https://example.com/blocked"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body"
          },
          "401": {
            "description": "Missing, invalid, or revoked API key",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CheckResponse" }
              }
            }
          },
          "403": {
            "description": "Tenant account is suspended"
          },
          "429": {
            "description": "API-level rate limit exceeded (50 req/sec per IP)"
          },
          "500": {
            "description": "Internal evaluation error — treat as BLOCK and retry with backoff"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "CheckRequest": {
        "type": "object",
        "required": ["apiKey"],
        "properties": {
          "apiKey": {
            "type": "string",
            "pattern": "^bzf_[0-9a-f]{48}$",
            "description": "Your tenant API key (bzf_ prefix + 48 hex characters). Identifies which tenant's rules to evaluate. Never expose this in client-side code — always call from your backend."
          },
          "ip": {
            "type": "string",
            "description": "IPv4 address of the end user. Used by IP blocklist/allowlist and rate limit rules.",
            "example": "1.2.3.4"
          },
          "country": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "description": "ISO 3166-1 alpha-2 country code of the request origin. Used by geo rules. Country detection is your responsibility — use Cloudflare CF-IPCountry, AWS CloudFront-Viewer-Country, or MaxMind GeoIP2.",
            "example": "US"
          },
          "path": {
            "type": "string",
            "description": "The URL path being requested on your application — everything after the domain. Used by path filter rules.",
            "example": "/api/orders/123"
          },
          "userAgent": {
            "type": "string",
            "description": "The User-Agent header value from the end user's request. Used by user agent / bot detection rules."
          },
          "lat": {
            "type": "number",
            "minimum": -90,
            "maximum": 90,
            "description": "Latitude of the request origin in decimal degrees. Required for geofence rules.",
            "example": 37.77
          },
          "lng": {
            "type": "number",
            "minimum": -180,
            "maximum": 180,
            "description": "Longitude of the request origin in decimal degrees. Required for geofence rules.",
            "example": -122.41
          },
          "timestamp": {
            "type": "integer",
            "description": "Unix timestamp in milliseconds. Defaults to server time if omitted.",
            "example": 1715123456789
          }
        }
      },
      "CheckResponse": {
        "type": "object",
        "required": ["decision", "reason"],
        "properties": {
          "decision": {
            "type": "string",
            "enum": ["ALLOW", "BLOCK", "REDIRECT"],
            "description": "ALLOW: request passed all rules, proceed normally. BLOCK: request matched a blocking rule, return HTTP 403 with the ghost response body. REDIRECT: request matched a redirect rule, return HTTP 302 or render the ghost response."
          },
          "reason": {
            "type": "string",
            "description": "Human-readable explanation of the decision.",
            "example": "Country CN is blocked"
          },
          "actionPayload": {
            "$ref": "#/components/schemas/ActionPayload",
            "description": "Present only when decision is BLOCK or REDIRECT. Contains the ghost response to return to the end user."
          }
        }
      },
      "ActionPayload": {
        "type": "object",
        "required": ["type", "value"],
        "description": "Ghost response configuration. Beezifi returns a seamless, configurable response that gives no indication of the actual security decision.",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["url", "html", "text"],
            "description": "url: redirect the user to an external URL (HTTP 302). html: return a fully custom HTML page (HTTP 403). text: return a plain text string (HTTP 403, useful for API clients)."
          },
          "value": {
            "type": "string",
            "description": "The redirect URL, custom HTML markup, or plain text body.",
            "example": "https://example.com/region-unavailable"
          }
        }
      }
    }
  },
  "x-rule-types": {
    "description": "Rules are evaluated in priority order (lowest number first). The first matching rule stops evaluation.",
    "types": [
      {
        "name": "ip_blocklist",
        "description": "Block specific IPv4 addresses or CIDR ranges.",
        "config": { "ips": ["192.168.1.5", "10.0.0.0/8"] },
        "actions": ["BLOCK", "REDIRECT"]
      },
      {
        "name": "ip_allowlist",
        "description": "Two modes: action BLOCK/REDIRECT restricts to only listed IPs; action ALLOW is a whitelist bypass that skips all further rules for listed IPs.",
        "config": { "ips": ["203.0.113.10", "198.51.100.0/24"] },
        "actions": ["ALLOW", "BLOCK", "REDIRECT"]
      },
      {
        "name": "geo_block",
        "description": "Block requests from specific countries (ISO 3166-1 alpha-2 codes).",
        "config": { "countries": ["CN", "RU", "KP"] },
        "actions": ["BLOCK", "REDIRECT"]
      },
      {
        "name": "geo_allow",
        "description": "Two modes: action BLOCK/REDIRECT restricts to only listed countries; action ALLOW is a whitelist bypass.",
        "config": { "countries": ["US", "CA", "GB"] },
        "actions": ["ALLOW", "BLOCK", "REDIRECT"]
      },
      {
        "name": "geofence",
        "description": "Restrict access by circular geographic area using the Haversine formula. Action BLOCK/REDIRECT applies to requests outside the fence; action ALLOW whitelists requests inside.",
        "config": { "lat": 37.7749, "lng": -122.4194, "radius": 50, "unit": "km" },
        "actions": ["ALLOW", "BLOCK", "REDIRECT"]
      },
      {
        "name": "rate_limit",
        "description": "Cap requests per IP or API key within a sliding time window.",
        "config": { "maxRequests": 100, "windowSeconds": 60, "identifier": "ip" },
        "actions": ["BLOCK", "REDIRECT"]
      },
      {
        "name": "user_agent",
        "description": "Block requests by User-Agent. block_bots enables built-in detection of common bots and scanners (Googlebot, sqlmap, nikto, curl, etc.). Custom patterns are case-insensitive regular expressions.",
        "config": { "block_bots": true, "patterns": ["sqlmap", "nikto", "^curl\\/"] },
        "actions": ["BLOCK", "REDIRECT"]
      },
      {
        "name": "path_filter",
        "description": "Restrict access to specific URL paths. Modes: prefix (path starts with pattern), exact (full match), regex (regular expression).",
        "config": { "paths": ["/admin", "/.env"], "mode": "prefix" },
        "actions": ["BLOCK", "REDIRECT"]
      }
    ]
  }
}
