Use Case • Kiosk

Check-in Kiosk

Scan badges and record check-ins securely and fast.

Goal

You want a kiosk app (tablet/laptop) that scans a QR/badge code and records a check-in.

What you need

  • An API key with badges:write.
  • A small server to proxy requests (recommended).

Flow

  1. 1) Scanner reads badge code.
  2. 2) Your kiosk app calls your own server endpoint (no secrets in kiosk).
  3. 3) Your server calls Confera Public API.
  4. 4) Kiosk shows success/failure instantly.

Request

Direct (server-to-server)
bash
curl -X POST "https://your-domain/api/public/v1/badges/checkin" \
  -H "X-API-Key: cat_..." \
  -H "Content-Type: application/json" \
  -d '{"qr":"ABC123","location":"kiosk-1"}'

Proxy endpoint (recommended)

Kiosks are often semi-trusted devices. Keep your Confera API key on a server you control, then let the kiosk call your server.

Next.js Route Handler: /api/kiosk/checkin
ts
import { NextResponse } from "next/server";
import { createConferaPublicClient, isConferaApiError } from "@confera/sdk";

const confera = createConferaPublicClient({
  baseUrl: process.env.CONFERA_BASE_URL!,
  apiKey: process.env.CONFERA_API_KEY!,
  timeoutMs: 8000,
  userAgent: "kiosk/1.0",
});

export async function POST(req: Request) {
  const body = (await req.json()) as { qr?: string; location?: string };
  if (!body.qr || !body.location) {
    return NextResponse.json({ ok: false, error: "Missing qr or location" }, { status: 400 });
  }

  try {
    const res = await confera.badges.checkin({ qr: body.qr, location: body.location });
    return NextResponse.json({ ok: true, data: res.data });
  } catch (e) {
    // Idempotent UX: duplicate scans should still show “checked in”.
    if (isConferaApiError(e) && e.status === 409) {
      return NextResponse.json({ ok: true, duplicate: true });
    }

    if (isConferaApiError(e)) {
      return NextResponse.json({ ok: false, status: e.status, code: e.code, message: e.message }, { status: 502 });
    }

    return NextResponse.json({ ok: false, message: "Unexpected error" }, { status: 500 });
  }
}

Kiosk call

Browser / kiosk app
ts
const res = await fetch("/api/kiosk/checkin", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ qr: scannedCode, location: "kiosk-1" }),
});

const json = await res.json();
if (!json.ok) throw new Error(json.message ?? "Check-in failed");

// json.duplicate === true means “already checked in” → show success UI
console.log("OK", json);

Error handling

  • 401: key missing/invalid/revoked/expired.
  • 403: conference inactive, plan ended, module disabled, or scope missing.
  • 409: duplicate scan (treat as success in kiosk UX).
  • 429: rate limit (slow down scans, retry with backoff).
  • 503: temporary outage (try again).