| Audience | Engineers instrumenting Hightouch Events |
| Prerequisites | An event source and at least one event contract |
The Events CLI reads your event contracts and generates typed wrappers around supported Hightouch Events SDKs, such as the Browser and iOS SDKs. You call those wrappers in your app instead of sending untyped track calls.
This page is for the Events CLI (htevents). It is a different tool from the Hightouch CLI (ht), which manages workspace resources such as models and syncs.
Overview
Contracts define the events and fields Hightouch expects. The Events CLI generates typed functions from those contracts. You call the functions from application code.
When a contract changes, TypeScript, Python, and other typed languages flag mismatches in your editor. Hightouch still validates events when they arrive. The CLI adds an additional check that happens earlier, in the code you write.
Use the CLI when you instrument with a Hightouch Events SDK and you want generated helpers that match your contracts. Skip it if you send events only through the HTTP API or a streaming source such as Kafka.
The CLI never installs or constructs the Events SDK — you still initialize the SDK yourself. Generated files only wrap it.
Before you begin
Before you generate wrappers, make sure you have:
- Node.js 18 or later, which includes
npmandnpx - An event source in Hightouch
- At least one event contract in a domain attached to that source
- The Events SDK for your language, installed in the same project
Copy the source slug from the event source. Go to Event Collection > Event sources, open the source, and click the Setup tab. The Slug field identifies this source in Git Sync YAML and the Events CLI. It is not the write key.
Install the CLI
Install the CLI as a development dependency:
npm install --save-dev @ht-sdks/events-cli
Run it from the project directory with npx:
npx htevents --help
A local install does not put htevents on your PATH; npx resolves the copy in node_modules. To put it on your PATH, install globally with npm install -g @ht-sdks/events-cli. Prefer the local install above so the CLI version stays pinned in CI and shared project environments.
If your repo has no package.json (for example, a Swift or Android app), npm install --save-dev will create one. You can also run the CLI without adding a dependency using:
npx @ht-sdks/events-cli --help
Create a configuration file
From your application repository, run:
npx htevents init
init asks for:
- The event source slug
- Whether to load contracts from the Hightouch API or a local Git Sync checkout
- Which SDK to generate for
- Where to write the generated files
It writes htevents.config.json. Commit that file. Do not put API tokens in it.
Non-interactive init
In CI or scripts, pass every value as a flag:
npx htevents init \
--source web-app \
--input api \
--sdk browser-ts \
--output ./src/analytics/generated.ts
--input git-sync also requires --git-sync-path. Use --force to overwrite an existing configuration file.
Load contracts from the API
API input fetches the contracts attached to your event source from Hightouch.
Create an API key as a workspace Admin:
- From the API keys tab on the Settings page, select Add API key.
- Enter a descriptive Name for your key.
- Copy your API key and store it in a safe location. The key will only be displayed once.
- Click Create API key.
API keys authenticate as the user who created them. See API overview for permissions and what happens if that user loses access.
Pass the key as HIGHTOUCH_API_TOKEN or --token. --token wins when both are set.
export HIGHTOUCH_API_TOKEN="YOUR_API_KEY"
npx htevents generate
Never store the API key in htevents.config.json. The CLI rejects a
configuration file that contains token, apiKey, or api_key.
Load contracts from Git Sync
If your workspace version-controls event contracts, you can generate from a local checkout instead of the API. No API key is required.
Set input to git-sync and point path at the Git Sync repository root or its events directory:
{
"source": "web-app",
"input": { "type": "git-sync", "path": "./events" },
"outputs": [{ "sdk": "browser-ts", "path": "./src/analytics/generated.ts" }]
}
The CLI reads events/domains (current layout) or events/contracts (legacy layout). Don't mix both layouts in the same repository.
Generate wrappers
npx htevents generate
generate writes typed wrappers to each path in outputs and writes htevents.lock.json next to the configuration file. The lock file records which contract versions produced the code.
Do not edit generated files. When contracts change, run generate again.
Commit htevents.config.json. You can commit the generated sources and htevents.lock.json, or add them to .gitignore and run generate after clone and in CI.
Committing generated files lets htevents check fail a PR when contracts changed but wrappers were not regenerated. If you ignore them, run generate in CI before you compile instead of check.
Configuration file
htevents.config.json looks like this:
{
"$schema": "./node_modules/@ht-sdks/events-cli/schemas/config.schema.json",
"source": "web-app",
"input": { "type": "api" },
"outputs": [{ "sdk": "browser-ts", "path": "./src/analytics/generated.ts" }]
}
| Field | What it does |
|---|---|
$schema | Optional. Points at the JSON Schema shipped with the package so editors can validate the file. |
source | Event source slug from the Setup tab. |
input | api or git-sync. Git Sync also needs path. |
outputs | One or more { "sdk", "path" } entries. Paths are relative to the configuration file. |
To generate for more than one SDK, add another outputs entry:
{
"outputs": [
{ "sdk": "browser-ts", "path": "./src/analytics/generated.ts" },
{ "sdk": "node-ts", "path": "./server/analytics/generated.ts" }
]
}
PHP writes several files. Set path to a directory, not a single file.
Pass -c / --config when the file is not ./htevents.config.json. generate and check resolve paths from that file's directory, not from the current working directory.
Call generated wrappers
Install and initialize the Events SDK the same way you would without the CLI. Then import the generated helpers.
For browser-ts, bind the SDK instance once, then call a wrapper for each event:
import { HtEventsBrowser } from "@ht-sdks/events-sdk-js-browser";
import { setHtEvents, trackOrderCompleted } from "./src/analytics/generated";
const analytics = HtEventsBrowser.load(
{ writeKey: "WRITE_KEY" },
{ apiHost: "us-east-1.hightouch-events.com" },
);
setHtEvents(analytics);
trackOrderCompleted({ orderId: "abc-123", total: 49.99 });
Replace WRITE_KEY and apiHost with the values from the event source Setup tab. See the Browser SDK for initialization options.
Each contract version becomes a named wrapper. Order Completed version v2 becomes trackOrderCompletedV2 in TypeScript, or track_order_completed_v2 in Python and Ruby.
The latest version of each event also gets an unversioned alias, such as trackOrderCompleted. Wrappers inject the schema version on the event so Hightouch validates against the matching contract. You do not need to set context.htevents.schemaVersion yourself.
Other SDKs follow the same pattern. Some languages take the SDK client as an argument instead of calling setHtEvents.
Keep generated code in sync
htevents check rebuilds the expected files in memory and compares them to disk. It exits 0 when they match. It exits 2 when a generated file is missing or different:
Generated files are out of date:
src/analytics/generated.ts
Run `htevents generate` to update.
If generated files are committed, run check in CI so a contract change cannot land without regenerating wrappers:
- run: npx htevents check
env:
HIGHTOUCH_API_TOKEN: ${{ secrets.HIGHTOUCH_API_TOKEN }}
If generated files are gitignored, run generate in CI before you compile. check always reports drift when those files are missing.
If you generate from Git Sync, check out that repository in CI and omit the token.
Supported SDKs
Set outputs[].sdk to one of these identifiers. Install the matching Events SDK in the same project.
| CLI identifier | Events SDK | SDK docs |
|---|---|---|
browser-ts | @ht-sdks/events-sdk-js-browser | Browser |
node-ts | @ht-sdks/events-sdk-js-node | Node.js |
python | events-sdk-python | Python |
ruby | events-sdk-ruby | Ruby |
php | ht-sdks/events-sdk-php | PHP |
csharp | Hightouch.Events.CSharp | C# (.NET) |
go | github.com/ht-sdks/events-sdk-go | Go |
swift | events-sdk-swift | iOS |
android | com.hightouch.analytics.android:analytics | Android |
react-native | @ht-sdks/events-sdk-react-native | React Native |
flutter | @ht-sdks/events-sdk-flutter | Flutter |
kotlin | com.github.ht-sdks.events-sdk-kotlin:core | Coming soon |
java | com.github.ht-sdks.events-sdk-java:analytics | Java |
Generated files record the minimum peer SDK version they were tested against.
Commands
htevents [options] [command]
Global options
| Option | Description |
|---|---|
-c, --config <path> | Path to the configuration file. Default: ./htevents.config.json. |
--token <token> | Workspace API token. Overrides HIGHTOUCH_API_TOKEN. |
--debug | Print stack traces for errors. |
-V, --version | Print the CLI version. |
init
Creates htevents.config.json.
| Option | Description |
|---|---|
--source <slug> | Event source slug. |
--input <type> | api or git-sync. |
--git-sync-path <path> | Local Git Sync directory. Required with --input git-sync. |
--sdk <sdk> | Target SDK. Default: browser-ts. |
--output <path> | Output path for generated code. |
--force | Overwrite an existing configuration file. |
generate
Fetches contracts and writes typed wrappers plus htevents.lock.json.
check
Verifies generated files match the current contracts. Exit code 2 means they are out of date.
Troubleshooting
Authentication failed (401)
Cause: --token or HIGHTOUCH_API_TOKEN is missing, expired, or not a workspace API key.
Resolution: Create a new API key as an Admin and pass it to generate or check. See API overview.
Event source slug was rejected (422)
Cause: The source value in the configuration file is not a valid event source slug.
Resolution: Copy the Slug from the event source Setup tab. Do not use the write key or the source name.
Event domains API returned 404
Cause: The API key's workspace cannot list event domains.
Resolution: Confirm you can open Event Collection > Contracts in that workspace. Confirm the API key belongs to the same workspace as the event source.
Generated files are out of date
Cause: Contracts changed, or generated files were edited by hand.
Resolution: Run htevents generate and commit the updated files.
Configuration file contains a token
You may see this error if htevents.config.json includes a secret:
Config must not contain "token". Pass the API token via --token or the HIGHTOUCH_API_TOKEN environment variable.
Cause: The configuration file includes token, apiKey, or api_key.
Resolution: Remove the secret from the file. Pass it with --token or HIGHTOUCH_API_TOKEN.
Next steps
- Define or update event contracts for the events you generate wrappers for.
- Review how Hightouch handles contract violations.
- Initialize the Events SDK for your platform — for example Browser or iOS.