API Reference

SwiftGuard analyzes Swift source code for concurrency bugs, Sendable violations, and common pitfalls using AST parsing. All responses are JSON.

Authentication

Pass your API key in the Authorization header. For testing, use the demo key.

Authorization: Bearer sg_demo_key_2026

The demo key is rate-limited to 100 requests/minute. Authentication is optional for the live demo on the landing page.

Endpoint

POST/api/v1/review

Request Body

{
  "source": "let x: String? = nil\nlet y = x!",
  "swiftVersion": "6.0",     // optional
  "platform": "ios"          // optional
}

source (required) — Swift source code as a string.

swiftVersion (optional) — Target Swift version. Default: latest.

platform (optional) — Target platform (ios, macos, server). For future use.

Response Format

{
  "issues": [
    {
      "rule": "force-unwrap",
      "severity": "warning",
      "message": "Force unwrap operator used. This will crash at runtime if the value is nil.",
      "line": 2,
      "column": 12,
      "confidence": 0.95,
      "suggestion": "Use optional binding (if let/guard let) or the nil-coalescing operator (??) instead."
    }
  ],
  "metadata": {
    "rulesApplied": 7,
    "parseTimeMs": 3,
    "astValid": true
  }
}

issues[] — Array of detected problems.

issues[].rule — Rule identifier.

issues[].severity"error" | "warning" | "info"

issues[].confidence — 0.0 to 1.0. Higher means more certain.

issues[].suggestion — Recommended fix.

metadata.rulesApplied — Number of rules evaluated.

metadata.parseTimeMs — Parse time in milliseconds.

metadata.astValid — Whether the AST parsed without errors.

Rules Reference

Rule IDSeverityConfidenceDescription
force-unwrapwarning0.50–0.95Detects force unwrap operator (!) usage that can cause runtime crashes
unsafe-unchecked-sendablewarning0.85–0.90Flags @unchecked Sendable conformance on types with mutable stored properties
actor-isolation-violationerror0.85–0.95Detects cross-isolation access to actor state from non-async or detached contexts
non-sendable-boundary-crossingwarning0.80–0.95Non-Sendable types captured or passed across concurrency boundaries
task-data-race-riskerror0.88–0.92Shared mutable state accessed or mutated inside Task closures
missing-sendable-closurewarning0.85Closure/function types in actors or Sendable contexts missing @Sendable
missing-sendable-conformanceinfo0.75Types used as actor method parameters without Sendable conformance

Code Examples

curl

curl -X POST https://your-domain.com/api/v1/review \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sg_demo_key_2026" \
  -d '{"source": "let x: String? = nil\nlet y = x!"}'

Swift (URLSession)

import Foundation

let url = URL(string: "https://your-domain.com/api/v1/review")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer sg_demo_key_2026", forHTTPHeaderField: "Authorization")

let body: [String: Any] = [
    "source": "let x: String? = nil\nlet y = x!",
    "swiftVersion": "6.0"
]
request.httpBody = try JSONSerialization.data(withJSONObject: body)

let (data, _) = try await URLSession.shared.data(for: request)
let result = try JSONDecoder().decode(ReviewResponse.self, from: data)
print("Found \(result.issues.count) issues")

Python (requests)

import requests

response = requests.post(
    "https://your-domain.com/api/v1/review",
    headers={
        "Authorization": "Bearer sg_demo_key_2026",
        "Content-Type": "application/json",
    },
    json={
        "source": "let x: String? = nil\nlet y = x!",
        "swiftVersion": "6.0",
    },
)

data = response.json()
for issue in data["issues"]:
    print(f"[{issue['severity']}] {issue['rule']}: {issue['message']}")

Rate Limits

To keep the service reliable for everyone, the API is rate-limited to 100 requests per minute.

When rate limited, the API returns HTTP 429 with a JSON error body.

Error Responses

StatusDescription
400Invalid JSON body or missing source field
401Invalid or malformed API key
429Rate limit exceeded (100 req/min)