Use Case • Registrations

External Registration Form

Run registrations on your own website or through a vendor — without exposing secrets.

Goal

You want people to register from a website that isn’t Confera (or from a vendor’s form), but still save the registration inside Confera.

What you need

  • An API key with registrations:read and registrations:write.
  • A small server endpoint that your website calls (recommended).
  • A way to upload/collect a receipt URL (depends on your payment flow).

Step 1: Get config

First, fetch the “registration config”. This tells you which fields are required, which ticket types exist, which payment methods are active, and whether a pricing phase is open.

Fetch config
bash
curl "https://your-domain/api/public/v1/registrations/config" \
  -H "X-API-Key: cat_..."

Step 2: Build the form

Use the config response to render your form:

  • Render ticket_types as a dropdown.
  • Render payment_methods as a dropdown.
  • Render fields (only the enabled ones) and enforce required fields.
  • If public_registration_enabled is false, show a friendly “closed” message.
  • If open_phase is null, registrations are enabled but pricing is closed (show “try later”).

Step 3: Submit

Submit the registration from your server. Keep the key secret.

Create registration
bash
curl -X POST "https://your-domain/api/public/v1/registrations/registrations" \
  -H "X-API-Key: cat_..." \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Aisha",
    "lastName": "Khan",
    "email": "aisha@example.com",
    "ticketTypeId": "<ticket_type_id>",
    "paymentMethodId": "<payment_method_id>",
    "paymentReference": "TXN-12345",
    "paymentProofUrl": "https://example.com/receipt.png",
    "customFields": {
      "dietary": "Vegetarian"
    }
  }'
SDK (recommended)
ts
import { createConferaPublicClient } from "@confera/sdk";

const confera = createConferaPublicClient({
  baseUrl: "https://your-domain",
  apiKey: process.env.CONFERA_API_KEY!,
});

const cfg = await confera.registrations.getConfig();
if (!cfg.data.public_registration_enabled) throw new Error("Registrations are closed");

await confera.registrations.create({
  firstName: "Aisha",
  lastName: "Khan",
  email: "aisha@example.com",
  ticketTypeId: "<ticket_type_id>",
  paymentMethodId: "<payment_method_id>",
  paymentReference: "TXN-12345",
  paymentProofUrl: "https://example.com/receipt.png",
});

Server endpoint (recommended)

Your website should call your endpoint, and your endpoint calls Confera. This keeps the API key secret and lets you enforce your own validation.

Next.js Route Handler: /api/registration (GET config + POST submit)
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: 12000,
  userAgent: "registration-form/1.0",
});

export async function GET() {
  const cfg = await confera.registrations.getConfig();
  return NextResponse.json(cfg);
}

export async function POST(req: Request) {
  const body = (await req.json()) as Record<string, unknown>;

  try {
    const created = await confera.registrations.create(body as any);
    return NextResponse.json({ ok: true, registration: created.data });
  } catch (e) {
    if (isConferaApiError(e)) {
      // Convert upstream errors into a safe, consistent shape for your UI.
      return NextResponse.json(
        { ok: false, status: e.status, code: e.code, message: e.message, details: e.details },
        { status: 400 }
      );
    }
    return NextResponse.json({ ok: false, message: "Unexpected error" }, { status: 500 });
  }
}
Browser UI: fetch config + submit
ts
// Config (for rendering the form)
const cfg = await fetch("/api/registration").then((r) => r.json());

// Submit
const res = await fetch("/api/registration", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    firstName: "Aisha",
    lastName: "Khan",
    email: "aisha@example.com",
    ticketTypeId: "<ticket_type_id>",
    paymentMethodId: "<payment_method_id>",
    paymentReference: "TXN-12345",
    paymentProofUrl: "https://example.com/receipt.png",
  }),
});

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

Security

  • Never put the API key in browser code or a website builder.
  • Use one key per vendor/integration, and rotate keys regularly.
  • If the conference is not live or the plan ends, keys stop working automatically.