Leads

Receive contact form submissions from your sites via the API. Leads appear in the CMS dashboard and trigger notifications via Discord, email, and webhooks.

How Leads Work

When a visitor submits a form on your site, you send the data to the leads API. The CMS creates a lead record and triggers notifications to workspace owners and admins.

At least one of email or phone is required. You can also include a source to identify which form or page the lead came from, and pass any custom data in the data field.

Submitting Leads

Security: Always proxy leads through your own API route. Never expose your CMS API key in client-side code.

Your API route (server-side)
// app/api/contact/route.ts
export async function POST(request: Request) {
  const body = await request.json();

  const res = await fetch(
    `${process.env.CMS_URL}/api/public/leads`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-api-key": process.env.CMS_API_KEY!,
      },
      body: JSON.stringify({
        email: body.email,
        firstName: body.firstName,
        lastName: body.lastName,
        source: "contact-form",
        message: body.message,
      }),
    }
  );

  if (!res.ok) {
    return Response.json({ error: "Failed to submit" }, { status: 400 });
  }
  return Response.json({ success: true });
}
Client-side form
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
  e.preventDefault();
  const form = new FormData(e.currentTarget);

  const res = await fetch("/api/contact", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      email: form.get("email"),
      firstName: form.get("firstName"),
      message: form.get("message"),
    }),
  });

  if (res.ok) {
    // Show success message
  }
}

Anti-Spam

The leads API supports a honeypot field. Add a hidden input to your form — if a bot fills it in, the request succeeds silently but no lead is created:

Honeypot pattern
<form onSubmit={handleSubmit}>
  {/* Visible fields */}
  <input name="email" type="email" required />
  <textarea name="message" required />

  {/* Hidden honeypot - bots will fill this in */}
  <input
    name="honeypot"
    type="text"
    style={{ display: "none" }}
    tabIndex={-1}
    autoComplete="off"
  />

  <button type="submit">Send</button>
</form>

Notifications

When a lead is created, the CMS automatically sends notifications:

  • Discord — notification to your workspace's Discord webhook
  • Email — to workspace owners and admins
  • Webhook — POST to your configured webhook URL

Next Steps