JSON Schema
Download the machine-readable schema for the Events v2 batch.
The Events v2 batch has a published JSON Schema. Point a validator at it and you find a malformed payload on your own machine, before you spend a request finding it in production.
Download: /protocol/events-v2.schema.json
It is draft 2020-12. Its $id is
https://www.getfounderhq.com/schemas/events-v2.json.
What the schema covers
| Rule | Enforced |
|---|---|
sent_at and batch are required, and nothing else is allowed at the top level | yes |
| A batch holds 1 to 100 events | yes |
Every event requires uuid, event, distinct_id, timestamp, properties, and options | yes |
Cookieless events require distinct_id: "$founderhq_cookieless" and both cookieless options | yes |
| Cookieless properties match the allowlist, with their length and range limits | yes |
A cookieless $pageview cannot carry page-leave properties | yes |
Two rules live in the API, not the schema, because they need context:
$event names must be on the reserved allowlist.- Key permissions and the server-side cookieless capability gate are enforced per event.
Validate your payload
Add ajv, then check a batch before you send it.
import Ajv from "ajv";
import addFormats from "ajv-formats";
const schema = await fetch("https://www.getfounderhq.com/docs/protocol/events-v2.schema.json").then((r) => r.json());
const validate = addFormats(new Ajv({ strict: false })).compile(schema);
if (!validate(batch)) console.error(validate.errors);ajv is the only thing you add. The schema itself has no dependencies and no remote references, so you can vendor the file into your repository and validate offline.
Passing the schema is not the same as being accepted
The schema proves the shape is right. FounderHQ still checks your key, your event names, and your distinct IDs at ingest. Read Wire protocol for the per-event result codes.