Use test keys (sk_test_…) in the playground. Test traffic never bills. Live keys need a licensed site.
AbuseGraphDocs
Guides

iOS integration (Swift)

Protect iOS signup and login through your backend and the AbuseGraph session and check APIs.

Keep the secret on your backend

Never include an sk_ key in an App Store binary. Have the app call an endpoint you own with the account and device fields. Your backend creates a short-lived session, binds it to a check, and returns the verdict.

App request

import Foundation

enum SignupError: Error {
    case riskCheckRejected
}

struct RiskCheckRequest: Encodable {
    let email: String
    let event: String
    let visitorId: String?
}

struct SignupResponse: Decodable {
    let ok: Bool
}

let url = URL(string: "https://your-api.example.com/signup-risk-check")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode(
    RiskCheckRequest(email: email, event: "signup", visitorId: visitorId)
)
let (data, response) = try await URLSession.shared.data(for: request)
guard (response as? HTTPURLResponse)?.statusCode == 200 else {
    throw SignupError.riskCheckRejected
}
let result = try JSONDecoder().decode(SignupResponse.self, from: data)
guard result.ok else { throw SignupError.riskCheckRejected }
// Continue only after the backend has approved and completed signup.

Backend flow

Your backend uses its server-held secret for both API calls. Store device fields in the session, then pass the returned sessionId with the account fields to check.

const headers = {
  "content-type": "application/json",
  "x-api-key": process.env.ABUSEGRAPH_SECRET_KEY!,
  "x-abusegraph-site": process.env.ABUSEGRAPH_SITE!,
};
const site = process.env.ABUSEGRAPH_SITE!;

const sessionResponse = await fetch("https://abusegraph.com/api/v1/session", {
  method: "POST",
  headers,
  body: JSON.stringify({ visitorId, fingerprint }),
});
if (!sessionResponse.ok) throw new Error("Unable to create risk session");
const { sessionId } = await sessionResponse.json();

const checkResponse = await fetch("https://abusegraph.com/api/v1/check", {
  method: "POST",
  headers,
  body: JSON.stringify({ email, event, site, sessionId }),
});
if (!checkResponse.ok) throw new Error("Unable to check account risk");
const result = await checkResponse.json();
if (result.verdict === "block") return Response.json({ ok: false }, { status: 403 });
if (result.verdict === "challenge") return Response.json({ ok: false }, { status: 428 });

// Create the account / issue the session here, after the decision.
return Response.json({ ok: true });

The session expires after 24 hours. Events: signup, login, password_reset, and email_change. See Android and React Native.