Skip to content
useEventStack 0.3.0 is live.Read the quickstart

Build

Define the event before ingestion

Register an organization contract with type and required_fields, then send the matching payload version.

Prerequisites

You need a verified signed-in user session, membership in the target organization, and a stable event name. Event types are lowercase dotted text, contain only lowercase letters, digits, underscores, and dots, and are at most 120 characters.

Working flow

1. Name a completed fact

acme.deployment_completed
sales.opportunity_closed
user.signup_verified

Keep changing values such as customer identifiers, versions, and dates in the payload rather than in type.

2. Register the organization contract

Use Dashboard → Contracts. The dashboard sends a session-authenticated, CSRF-protected request to POST /organizations/:organization_id/event-contracts.

Option A: Full JSON Schema validation (recommended)

{
  "type": "acme.deployment_completed",
  "version": 1,
  "description": "A service deployment completed",
  "required_fields": ["service", "version", "environment", "status"],
  "schema": {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "required": ["service", "version", "environment", "status"],
    "properties": {
      "service": { "type": "string", "minLength": 1 },
      "version": { "type": "string" },
      "environment": { "type": "string", "enum": ["production", "staging", "sandbox"] },
      "status": { "type": "string", "enum": ["healthy", "degraded", "failed"] }
    },
    "additionalProperties": false
  }
}

When schema is provided, the API validates payloads against the full JSON Schema (type checks, enum, pattern, nested objects, additionalProperties).

Option B: Required fields only

{
  "type": "acme.deployment_completed",
  "version": 1,
  "description": "A service deployment completed",
  "required_fields": ["service", "version", "environment", "status"]
}

Without a schema, only top-level field presence is enforced.

3. Emit the matching version

import type {
  UseEventStackClient,
  UseEventStackEnvironment,
} from '@useeventstack/sdk';

export async function sendDeployment(useeventstack: UseEventStackClient) {
  const environment: UseEventStackEnvironment = 'sandbox';

  return useeventstack.events.emit({
    type: 'acme.deployment_completed',
    environment,
    schemaVersion: 1,
    payload: {
      service: 'api',
      version: '1.0.0',
      environment,
      status: 'healthy',
    },
  });
}

There are no built-in event types and no event catalogue in the SDK. The name is entirely yours — acme. above is just a namespace, use whatever your domain calls the fact. The SDK accepts any lowercase dotted name and takes your payload type as a type argument; the registered organization contract is the runtime check.

Expected response

Contract registration returns the active organization record:

{
  "id": "…",
  "organization_id": "…",
  "type": "acme.deployment_completed",
  "version": 1,
  "description": "A service deployment completed",
  "required_fields": ["service", "version", "environment", "status"],
  "status": "active",
  "updated_at": "…"
}

After that record exists, an event with metadata.schema_version: 1 and all four payload keys can pass contract validation.

Failure diagnosis

  • Invalid event type: include at least one dot and use only the supported lowercase characters.
  • Contract not registered: confirm organization, type, and version all match the event.
  • invalid_event_payload: inspect error.details.field for the missing top-level payload key.
  • Dashboard save rejected: confirm the account is verified and the session request includes the current CSRF token.

Validation modes

Event contracts support two validation modes:

  • JSON Schema validation (recommended) — when a schema field is provided during contract registration, incoming payloads are validated against the full JSON Schema (Draft-07). This includes type checking, nested object validation, format constraints, enum enforcement, and pattern matching.
  • Required fields validation (legacy) — when only required_fields is provided, the API checks that each listed field is present as a top-level payload key. No type or structure validation is performed.

A matching contract does not automatically create or trigger a workflow — workflows must be configured separately with a matching trigger_event.

Next step

Use the complete client setup in the TypeScript SDK guide, or return to the quickstart to verify the event in Activity.