{
  "openapi": "3.1.0",
  "info": {
    "title": "TxShield API",
    "version": "1.0.0",
    "description": "Pre-flight transaction intelligence for Solana mainnet. Drop unsigned transactions in, get back an approve / warn / block verdict in under 80 ms.",
    "contact": { "name": "TxShield", "email": "hello@txshield.dev", "url": "https://txshield.dev" },
    "license": { "name": "Proprietary", "url": "https://txshield.dev/security" }
  },
  "servers": [{ "url": "https://txshield.dev", "description": "Production" }],
  "tags": [
    { "name": "auth", "description": "Account creation, login, session management." },
    { "name": "solana", "description": "Solana pre-flight simulation, history, aggregate stats." },
    { "name": "api-keys", "description": "Programmatic API key management." },
    { "name": "billing", "description": "Pay-as-you-go subscription, Stripe integration." },
    { "name": "platform", "description": "Status, plans, health." }
  ],
  "security": [
    { "ApiKeyAuth": [] },
    { "BearerAuth": [] }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Server-to-server traffic. Issued by `POST /api/v1/api-keys`."
      },
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Dashboard / human flows. Issued by `POST /auth/login`."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code":       { "type": "string", "example": "invalid_transaction" },
              "message":    { "type": "string" },
              "request_id": { "type": "string", "example": "req_01HVZX9P3J4D2TJYP91D" }
            }
          }
        }
      },
      "RegisterRequest": {
        "type": "object",
        "required": ["email", "password"],
        "properties": {
          "email":    { "type": "string", "format": "email" },
          "password": { "type": "string", "minLength": 8 }
        }
      },
      "AuthResponse": {
        "type": "object",
        "required": ["token", "refresh_token"],
        "properties": {
          "token":         { "type": "string", "description": "JWT access token (24h expiry)." },
          "refresh_token": { "type": "string", "description": "Refresh token (30d expiry)." }
        }
      },
      "User": {
        "type": "object",
        "required": ["id", "email", "role", "created_at"],
        "properties": {
          "id":         { "type": "string", "format": "uuid" },
          "email":      { "type": "string", "format": "email" },
          "name":       { "type": "string" },
          "role":       { "type": "string", "enum": ["user", "admin"] },
          "email_verified": { "type": "boolean" },
          "timezone":   { "type": "string", "example": "UTC" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "ApiKey": {
        "type": "object",
        "required": ["id", "prefix", "name", "created_at", "requests_count"],
        "properties": {
          "id":              { "type": "string", "format": "uuid" },
          "name":            { "type": "string", "example": "production-api" },
          "prefix":          { "type": "string", "example": "txshield_live_" },
          "key":             { "type": "string", "description": "Cleartext — only present in the response of POST /api/v1/api-keys." },
          "requests_count":  { "type": "integer" },
          "last_used_at":    { "type": "string", "format": "date-time", "nullable": true },
          "expires_at":      { "type": "string", "format": "date-time", "nullable": true },
          "created_at":      { "type": "string", "format": "date-time" }
        }
      },
      "ApiKeyCreateRequest": {
        "type": "object",
        "required": ["name"],
        "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 100 } }
      },
      "SimulateRequest": {
        "type": "object",
        "required": ["transaction"],
        "properties": {
          "transaction": {
            "type": "string",
            "format": "byte",
            "description": "Serialized VersionedTransaction (or legacy Transaction), base64-encoded. Signature slots may be empty/zero — we don't verify them."
          },
          "vectors": {
            "type": "array",
            "items": { "type": "string", "enum": ["mev", "slippage", "rug", "program", "priority_fee", "simulation"] },
            "description": "Restrict which detection vectors run. Default: all."
          },
          "timeout_ms": {
            "type": "integer",
            "minimum": 50,
            "maximum": 800,
            "default": 800,
            "description": "Server-side timeout cap (ms)."
          }
        }
      },
      "PriorityFees": {
        "type": "object",
        "required": ["low", "medium", "high", "very_high", "samples"],
        "properties": {
          "low":       { "type": "integer", "description": "P25 microlamports per CU." },
          "medium":    { "type": "integer", "description": "P50 microlamports per CU." },
          "high":      { "type": "integer", "description": "P75 microlamports per CU." },
          "very_high": { "type": "integer", "description": "P95 microlamports per CU." },
          "samples":   { "type": "integer", "description": "Number of programs sampled." }
        }
      },
      "Risk": {
        "type": "object",
        "required": ["mev_score", "mev_level", "has_blacklisted_program", "blacklisted_programs", "dex_programs", "risk_level"],
        "properties": {
          "mev_score": { "type": "number", "minimum": 0, "maximum": 1 },
          "mev_level": { "type": "string", "enum": ["none", "low", "medium", "high", "critical"] },
          "mev_type":  { "type": "string", "enum": ["sandwich", "jit", "backrun_only"], "nullable": true },
          "has_blacklisted_program": { "type": "boolean" },
          "blacklisted_programs":    { "type": "array", "items": { "type": "string" } },
          "dex_programs":            { "type": "array", "items": { "type": "string" } },
          "token_risk":              { "type": "object", "nullable": true },
          "risk_level": { "type": "string", "enum": ["low", "medium", "high", "critical"] }
        }
      },
      "SimulateResponse": {
        "type": "object",
        "required": ["success", "priority_fees", "risk", "recommendations"],
        "properties": {
          "success":                  { "type": "boolean", "description": "Did the inner Solana simulateTransaction succeed?" },
          "compute_units":            { "type": "integer", "nullable": true },
          "suggested_compute_limit":  { "type": "integer", "nullable": true },
          "fee_estimate_sol":         { "type": "number",  "nullable": true },
          "priority_fees":            { "$ref": "#/components/schemas/PriorityFees" },
          "slippage": {
            "type": "object", "nullable": true,
            "properties": {
              "bps":   { "type": "integer", "description": "Worst-case slippage in basis points." },
              "route": { "type": "string",  "description": "Chosen DEX route (e.g. \"jupiter-v6\")." }
            }
          },
          "risk":              { "$ref": "#/components/schemas/Risk" },
          "recommendations":   { "type": "array", "items": { "type": "object" } },
          "program_breakdown": { "type": "array", "items": { "type": "object" } },
          "call_tree":         { "type": "array", "items": { "type": "object" } },
          "failure_reason":    { "type": "string", "nullable": true },
          "failure_code":      { "type": "string", "nullable": true },
          "is_terminal":       { "type": "boolean" }
        }
      },
      "SimulationListResponse": {
        "type": "object",
        "required": ["simulations"],
        "properties": {
          "simulations": { "type": "array", "items": { "type": "object" } },
          "next_cursor": { "type": "string", "nullable": true }
        }
      },
      "StatsResponse": {
        "type": "object",
        "required": ["status", "total_simulations"],
        "properties": {
          "status":            { "type": "string", "enum": ["operational", "degraded", "down"] },
          "total_simulations": { "type": "integer" },
          "simulations_24h":   { "type": "integer" },
          "success_rate_24h":  { "type": "number" },
          "latency_p50_ms":    { "type": "number" },
          "latency_p95_ms":    { "type": "number" },
          "latency_p99_ms":    { "type": "number" },
          "uptime_pct":        { "type": "number" }
        }
      },
      "PlansResponse": {
        "type": "object",
        "required": ["model", "analysis_free_tier", "analysis_rate"],
        "properties": {
          "model":              { "type": "string", "enum": ["pay_as_you_go"] },
          "analysis_free_tier": { "type": "integer", "description": "Free simulations per day." },
          "analysis_rate":      { "type": "number",  "description": "EUR per simulation past the free tier." }
        }
      }
    }
  },
  "paths": {
    "/auth/register": {
      "post": {
        "tags": ["auth"], "summary": "Create an account", "security": [],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegisterRequest" } } } },
        "responses": {
          "200": { "description": "Account created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } },
          "422": { "description": "Validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/auth/login": {
      "post": {
        "tags": ["auth"], "summary": "Sign in", "security": [],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegisterRequest" } } } },
        "responses": {
          "200": { "description": "Tokens issued", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } },
          "401": { "description": "Bad credentials", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/auth/me": {
      "get": {
        "tags": ["auth"], "summary": "Current user", "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": { "description": "User profile", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } } }
        }
      }
    },
    "/auth/account": {
      "delete": {
        "tags": ["auth"], "summary": "Soft-delete current account", "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": { "description": "Account deleted", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } } } } } }
        }
      }
    },
    "/api/v1/api-keys": {
      "get": {
        "tags": ["api-keys"], "summary": "List keys", "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": { "description": "Keys (cleartext value never returned in list)", "content": { "application/json": { "schema": { "type": "object", "properties": { "keys": { "type": "array", "items": { "$ref": "#/components/schemas/ApiKey" } } } } } } }
        }
      },
      "post": {
        "tags": ["api-keys"], "summary": "Create a new key (cleartext returned ONCE)", "security": [{ "BearerAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKeyCreateRequest" } } } },
        "responses": {
          "200": { "description": "Key created — copy `key` field NOW", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKey" } } } }
        }
      }
    },
    "/api/v1/api-keys/{id}": {
      "delete": {
        "tags": ["api-keys"], "summary": "Revoke a key", "security": [{ "BearerAuth": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": { "200": { "description": "Revoked" }, "404": { "description": "Not found" } }
      }
    },
    "/api/v1/api-keys/{id}/rotate": {
      "post": {
        "tags": ["api-keys"], "summary": "Rotate (graceful — old key valid for 24h)", "security": [{ "BearerAuth": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "responses": {
          "200": { "description": "Rotated — new cleartext returned ONCE", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiKey" } } } }
        }
      }
    },
    "/api/v1/solana/tx/simulate": {
      "post": {
        "tags": ["solana"], "summary": "Pre-flight simulation — single transaction",
        "description": "Drops an unsigned VersionedTransaction in, runs all 14 detection vectors in parallel, returns the verdict envelope. Typical end-to-end latency: 68 ms p50, 184 ms p99.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SimulateRequest" } } } },
        "responses": {
          "200": { "description": "Verdict envelope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SimulateResponse" } } } },
          "401": { "description": "Missing/invalid auth" },
          "422": { "description": "Could not deserialize transaction bytes", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "description": "Rate limited — honour `Retry-After`" }
        }
      }
    },
    "/api/v1/solana/tx/simulate-batch": {
      "post": {
        "tags": ["solana"], "summary": "Batch simulate (up to 50 tx in one round-trip)",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "transactions": { "type": "array", "items": { "type": "string", "format": "byte" }, "maxItems": 50 } } } } } },
        "responses": {
          "200": { "description": "Verdicts in input order", "content": { "application/json": { "schema": { "type": "object", "properties": { "results": { "type": "array", "items": { "$ref": "#/components/schemas/SimulateResponse" } } } } } } }
        }
      }
    },
    "/api/v1/solana/simulations": {
      "get": {
        "tags": ["solana"], "summary": "Paginated simulation history",
        "parameters": [
          { "name": "limit",  "in": "query", "schema": { "type": "integer", "default": 25, "maximum": 200 } },
          { "name": "cursor", "in": "query", "schema": { "type": "string" } },
          { "name": "since",  "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "until",  "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "risk_level", "in": "query", "schema": { "type": "string", "enum": ["low", "medium", "high", "critical"] } }
        ],
        "responses": { "200": { "description": "Page of simulations", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SimulationListResponse" } } } } }
      }
    },
    "/api/v1/solana/simulations/stats": {
      "get": {
        "tags": ["solana"], "summary": "Pre-aggregated stats for the dashboard widget",
        "responses": { "200": { "description": "Aggregate stats", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatsResponse" } } } } }
      }
    },
    "/api/v1/billing/usage": {
      "get": {
        "tags": ["billing"], "summary": "Current billing-period usage", "security": [{ "BearerAuth": [] }],
        "responses": { "200": { "description": "Usage envelope" } }
      }
    },
    "/api/v1/billing/subscription": {
      "get": {
        "tags": ["billing"], "summary": "Active subscription for the signed-in user", "security": [{ "BearerAuth": [] }],
        "responses": { "200": { "description": "Subscription details" } }
      }
    },
    "/api/v1/billing/checkout": {
      "post": {
        "tags": ["billing"], "summary": "Create a Stripe Checkout session", "security": [{ "BearerAuth": [] }],
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "success_url": { "type": "string", "format": "uri" }, "cancel_url": { "type": "string", "format": "uri" } } } } } },
        "responses": {
          "200": { "description": "Redirect URL", "content": { "application/json": { "schema": { "type": "object", "properties": { "checkout_url": { "type": "string", "format": "uri" }, "session_id": { "type": "string" } } } } } }
        }
      }
    },
    "/api/v1/billing/portal": {
      "post": {
        "tags": ["billing"], "summary": "Create a Stripe Customer Portal session", "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": { "description": "Portal URL", "content": { "application/json": { "schema": { "type": "object", "properties": { "portal_url": { "type": "string", "format": "uri" } } } } } },
          "400": { "description": "No Stripe customer attached yet" }
        }
      }
    },
    "/api/v1/plans": {
      "get": {
        "tags": ["platform"], "summary": "Public pricing catalogue", "security": [],
        "responses": { "200": { "description": "Pay-as-you-go pricing", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PlansResponse" } } } } }
      }
    },
    "/api/v1/status": {
      "get": {
        "tags": ["platform"], "summary": "Current operational state + 24h aggregates", "security": [],
        "responses": { "200": { "description": "Status snapshot", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StatsResponse" } } } } }
      }
    },
    "/health": {
      "get": {
        "tags": ["platform"], "summary": "Liveness probe", "security": [],
        "responses": { "200": { "description": "ok" } }
      }
    }
  }
}
