QyzarQyzar/

Docs

Dashboard

Start

  • Overview
  • Quick start

SDKs

  • Browser SDK
  • Server helper

Guides

  • Client tokens
  • Verify sessions
  • Rate limiting
  • Uptime & status

API

  • API basics
  • HTTP routes

~4 min read

Rate limiting

Use project settings from the dashboard (mode, window, caps) or override them per check. Counters bucket by IP; optional metadata ties a limit to your user id and still requires the same IP.

Dashboard settings

In project settings, configure website rate limits: adaptive vs fixed mode, base/max caps, window length, and strike decay. Those values apply to every check unless you pass settingsOverride.

Server helper

Protect a route before heavy work
import { qyzar } from "@/lib/qyzar";

export async function POST(req: Request) {
  const ip = req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? "0.0.0.0";
  const userAgent = req.headers.get("user-agent") ?? "unknown";
  const userId = "…"; // from your session

  const rl = await qyzar.checkRateLimit(process.env.QYZAR_PROJECT_ID!, {
    ip,
    userAgent,
    metadata: userId, // same user on another IP gets a separate bucket
    sessionId: null,
    analytics: {
      path: "/api/checkout",
      method: "POST",
      baseUrl: "https://shop.example.com",
      body: { cartId: "…" },
      headers: { "content-type": "application/json" },
    },
  });

  if (!rl.allowed) {
    return Response.json(
      { error: "Too many requests", retryAfter: rl.retryAfter },
      { status: 429, headers: { "Retry-After": String(rl.retryAfter ?? 60) } }
    );
  }

  // … your handler
}

See also Server helper for all QyzarServer methods.

IP and metadata

  • Every check requires ip — counters are always scoped to that address.
  • Optional metadata (e.g. account id) adds a second dimension: the same metadata on a different IP does not share the limit.
  • Omit metadata to rate-limit by IP only for that project.

Override settings

await qyzar.checkRateLimit(projectId, {
  ip,
  userAgent,
  settingsOverride: {
    rateLimitMode: "default",
    rateLimitBaseMax: 200,
    rateLimitWindowSeconds: 120,
  },
});

Overrides apply only to that request; dashboard defaults are unchanged.

Denied-request analytics

When a check is denied by the adaptive/fixed cap (not a traffic rule block or challenge), Qyzar stores a request-log row with rateLimitHit: true and source rate_limit_denied. Pass analytics to attach optional request body, headers, and response snapshot (status, body, response headers) for investigation in the dashboard request log.

HTTP API

  • POST /projects/client/rate-limit-check — project secret (used by QyzarServer.checkRateLimit)
  • POST /projects/rate-limit/check — signed-in project owner (dashboard tooling)

These routes are excluded from platform HTTP abuse limiting so the checker cannot block itself. Full route list: HTTP routes.