> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hightouch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Events CLI

> 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](https://docs.hightouch.com/developer-tools/cli-guide.md) (`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](https://docs.hightouch.com/events/sdks/http.md) 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 `npm` and `npx`
* An [event source](https://docs.hightouch.com/events/sources/overview.md) in Hightouch
* At least one [event contract](https://docs.hightouch.com/events/contracts/management.md) 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:

```bash theme={null}
npm install --save-dev @ht-sdks/events-cli
```

Run it from the project directory with `npx`:

```bash theme={null}
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:

```bash theme={null}
npx @ht-sdks/events-cli --help
```

## Create a configuration file

From your application repository, run:

```bash theme={null}
npx htevents init
```

`init` asks for:

* The event source slug
* Whether to load contracts from the Hightouch API or a local [Git Sync](https://docs.hightouch.com/extensions/git-sync.md#event-contract-schema) 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:

```bash theme={null}
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:

1. From the [**API keys** tab](https://app.hightouch.com/settings/api-keys?from=docs) on the **Settings** page, click **Add API key**.
2. Enter a descriptive **Name** for your key.
3. Under **User group**, select the group whose permissions the key should have in this workspace, or select **All of the creator's groups** to give the key the same permissions as you.
4. Copy your **API key** and store it in a safe location. The key is only displayed once.
5. Click **Create API key**.

API keys authenticate as the user who created them. See [API overview](https://docs.hightouch.com/developer-tools/api-guide.md) 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.

```bash theme={null}
export HIGHTOUCH_API_TOKEN="YOUR_API_KEY"
npx htevents generate
```

> [!WARNING]
>
> 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](https://docs.hightouch.com/extensions/git-sync.md#event-contract-schema), 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:

```json theme={null}
{
  "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

```bash theme={null}
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:

```json theme={null}
{
  "$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:

```json theme={null}
{
  "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:

```jsx theme={null}
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](https://docs.hightouch.com/events/sdks/browser.md) 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:

```text theme={null}
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:

```yaml theme={null}
- 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](https://docs.hightouch.com/events/sdks/browser.md) |
| `node-ts` | `@ht-sdks/events-sdk-js-node` | [Node.js](https://docs.hightouch.com/events/sdks/nodejs.md) |
| `python` | `events-sdk-python` | [Python](https://docs.hightouch.com/events/sdks/python.md) |
| `ruby` | `events-sdk-ruby` | [Ruby](https://docs.hightouch.com/events/sdks/ruby.md) |
| `php` | `ht-sdks/events-sdk-php` | [PHP](https://docs.hightouch.com/events/sdks/php.md) |
| `csharp` | `Hightouch.Events.CSharp` | [C# (.NET)](https://docs.hightouch.com/events/sdks/csharp.md) |
| `go` | `github.com/ht-sdks/events-sdk-go` | [Go](https://docs.hightouch.com/events/sdks/go.md) |
| `swift` | `events-sdk-swift` | [iOS](https://docs.hightouch.com/events/sdks/ios.md) |
| `android` | `com.hightouch.analytics.android:analytics` | [Android](https://docs.hightouch.com/events/sdks/android.md) |
| `react-native` | `@ht-sdks/events-sdk-react-native` | [React Native](https://docs.hightouch.com/events/sdks/react-native.md) |
| `flutter` | `@ht-sdks/events-sdk-flutter` | [Flutter](https://docs.hightouch.com/events/sdks/flutter.md) |
| `kotlin` | `com.github.ht-sdks.events-sdk-kotlin:core` | Coming soon |
| `java` | `com.github.ht-sdks.events-sdk-java:analytics` | [Java](https://docs.hightouch.com/events/sdks/java.md) |

Generated files record the minimum peer SDK version they were tested against.

## Commands

```text theme={null}
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](https://docs.hightouch.com/developer-tools/api-guide.md).

### 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:

```text theme={null}
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](https://docs.hightouch.com/events/contracts/management.md) for the events you generate wrappers for.
* Review [how Hightouch handles contract violations](https://docs.hightouch.com/events/contracts/violations.md).
* Initialize the Events SDK for your platform — for example [Browser](https://docs.hightouch.com/events/sdks/browser.md) or [iOS](https://docs.hightouch.com/events/sdks/ios.md).
