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

~3 min read

Verify sessions

After verification, Qyzar sets cookies on your domain. Before checkout, account changes, or similar actions, ask Qyzar if that session is still valid.

Cookies (set by the browser SDK)

When connect/verify succeeds, ConnectVerifier (inside Qyzar) calls setConnectSessionCookies on your origin:

  • qyzar_session_id — session id (Elasticsearch document id)
  • qyzar_session_token — session JWT

Heartbeats via connect/reverify refresh the 15-minute cookie expiry. Read values on the client with getConnectSessionId() / getConnectSessionToken() from @tnuser/qyzar-client.

Browser — read session for your own API
"use client";

import {
  getConnectSessionId,
  getConnectSessionToken,
} from "@tnuser/qyzar-client";

async function callProtectedApi() {
  const sessionId = getConnectSessionId();
  const sessionToken = getConnectSessionToken();
  if (!sessionId || !sessionToken) {
    throw new Error("Not verified yet");
  }

  return fetch("/api/checkout", {
    method: "POST",
    credentials: "include", // sends qyzar_session_* cookies
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ sessionId, sessionToken }), // optional if route uses Cookie header
  });
}

Next.js App Router example

lib/qyzar.ts — one shared server client
import { QyzarServer } from "@tnuser/qyzar-server";

export const qyzar = new QyzarServer({
  apiBaseUrl: process.env.QYZAR_API_URL!,
  resolveProjectSecret: async () => process.env.QYZAR_PROJECT_SECRET!,
});
app/api/checkout/route.ts — protect a route
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { qyzar } from "@/lib/qyzar";

export async function POST() {
  const projectId = process.env.NEXT_PUBLIC_QYZAR_PROJECT_ID!;
  const cookieStore = await cookies();
  const cookieHeader = cookieStore
    .getAll()
    .map((c) => `${c.name}=${c.value}`)
    .join("; ");

  const result = await qyzar.verifySessionFromCookies(projectId, cookieHeader);

  if (!result.valid) {
    return NextResponse.json({ error: "Please verify first" }, { status: 401 });
  }

  // Safe to run checkout logic — result.sessionId, result.deviceId available
  return NextResponse.json({ ok: true });
}

Express-style example

middleware on protected routes
app.post("/api/checkout", async (req, res) => {
  const projectId = process.env.QYZAR_PROJECT_ID;
  const cookieHeader = req.headers.cookie ?? "";

  try {
    const result = await qyzar.verifySessionFromCookies(projectId, cookieHeader);
    if (!result.valid) {
      return res.status(401).json({ error: result.error ?? "Invalid session" });
    }
    // proceed…
    return res.json({ ok: true });
  } catch (e) {
    return res.status(500).json({ error: "Verification failed" });
  }
});

When you already have id + token

import { getConnectSessionId, getConnectSessionToken } from "@tnuser/qyzar-client";

// client
const sessionId = getConnectSessionId()!;
const sessionToken = getConnectSessionToken()!;

// server
const result = await qyzar.verifySession(projectId, {
  sessionId,
  sessionToken,
});

if (result.valid) {
  console.log(result.deviceId, result.lastVerify);
}

Raw HTTP

GET with Cookie header
const url = new URL("https://apisecure.qyzar.eu/projects/client/session-verify");
url.searchParams.set("projectId", projectId);

const res = await fetch(url, {
  method: "GET",
  headers: {
    Authorization: `Bearer ${projectSecret}`,
    Accept: "application/json",
    Cookie: req.headers.cookie,
  },
});
const data = (await res.json()).data;
// data.valid === true → ok

Client token vs session

Client tokens let the SDK connect. Session verification is what your own API uses to trust the visitor. See client tokens for reminting a bound JWT after cookies exist.