Documentation
Getting started

Quickstart: Server (Node)

Send events your backend owns from Node with a secret key.

Send an event your server knows about, and see it on the contact in FounderHQ. About 5 minutes.

Before you start

You need a FounderHQ account and a secret key. In the app, open Sequences → Settings → Event API keys, create a key for Backend, and copy it. The full key is shown only once. Keep it on your server, never in a browser or a mobile app.

Use the Node SDK for facts only your backend can prove: a signup that passed validation, a plan change, a webhook you received. Use a client SDK for what people do in the interface.

Install the package

npm install @founderhq/events-node

Create one client for your process

// lib/analytics.ts
import { FounderHqNode } from "@founderhq/events-node";

export const events = new FounderHqNode(process.env.FOUNDERHQ_SECRET_KEY!);

Put FOUNDERHQ_SECRET_KEY=fhq_sk_XXXX in your server environment. The client refuses a publishable key, so a mix-up fails at startup rather than in production.

Capture a server-truth event

Every server event names the contact it belongs to. Pass your own user ID, an email, or a phone number — at least one is required.

events.capture({
  contact: { externalId: "user_8421", email: "jane@acme.com" },
  event: "subscription.upgraded",
  properties: { plan: "growth", mrr: 99 },
});

Use the same externalId you pass to identify in the browser or the app. That is what keeps one contact instead of two.

Retrying a webhook? Pass a stable idempotencyKey so the same delivery counts once.

events.capture({
  contact: { externalId: "user_8421" },
  event: "subscription.upgraded",
  properties: { plan: "growth" },
  idempotencyKey: "stripe_evt_1a2b3c",
});

Flush before the process ends

The client batches in the background. Serverless functions and scripts exit too fast for that, so flush explicitly.

await events.flush();

Call await events.shutdown() when your server stops, to send what is left and stop the timer.

Verify

  1. Run the code path that captures the event.
  2. In FounderHQ, open Sequences → Contacts and open Jane.
  3. You see subscription.upgraded with plan: growth on her timeline.
  4. Sequences → Events shows the same event in the live stream.

Troubleshoot

The event never arrives

Pass an onError handler when you create the client. It reports every rejected or dropped event with the reason.

export const events = new FounderHqNode(process.env.FOUNDERHQ_SECRET_KEY!, {
  onError: (error, dropped) => console.error(error, dropped),
});

A second contact appeared for the same person

Your server and your client are using different IDs. Both must use the same stable user ID. See Identity and contacts.

An event starting with $ is ignored

Names that start with $ are reserved for the SDKs. Send your own name instead. Revenue has its own API — see Revenue.

Next

AI agent or LLM? Read this page as markdown

On this page