Schema Validation
Channels can define JSON Schema for their event types. When strict_types is enabled in the channel config, the server rejects events that do not conform to the schema.
Defining a Schema
Section titled “Defining a Schema”A schema file maps event type names to JSON Schema definitions:
{ "odds_shift": { "type": "object", "properties": { "market": { "type": "string" }, "shift": { "type": "number" } }, "required": ["market", "shift"] }, "market_close": { "type": "object", "properties": { "market": { "type": "string" }, "final_odds": { "type": "number" }, "resolved": { "type": "boolean" } }, "required": ["market", "final_odds"] }}Each key is an event type name. The value is a standard JSON Schema object that validates the event’s data field.
Creating a Channel with a Schema
Section titled “Creating a Channel with a Schema”npx zooid channel create market-signals --public --schema ./schema.jsonBy default, the schema is informational only. Events that do not match the schema are still accepted. The schema is published in the channel metadata so consumers know what to expect.
Strict Types
Section titled “Strict Types”Add the --strict flag to enforce the schema on publish:
npx zooid channel create market-signals --public --schema ./schema.json --strictThis sets config.strict_types: true. With strict types enabled:
- Events with a
typethat matches a schema key are validated against that schema - Events that fail validation are rejected with
422 Unprocessable Entityand a response body containing the validation errors - Events without a
typefield bypass schema validation entirely
Validation Error Response
Section titled “Validation Error Response”{ "error": "schema_validation_failed", "message": "Event data does not match schema for type 'odds_shift'", "details": [ { "path": "/shift", "message": "must be number" } ]}Updating a Schema
Section titled “Updating a Schema”Replace the schema on an existing channel:
npx zooid channel update market-signals --schema ./new-schema.jsonThis replaces the entire schema. There is no merging — if you remove a type from the new schema file, that type is no longer validated.
Enabling Strict Types on an Existing Channel
Section titled “Enabling Strict Types on an Existing Channel”npx zooid channel update market-signals --strictDisabling Strict Types
Section titled “Disabling Strict Types”npx zooid channel update market-signals --no-strictEvents Without a Type
Section titled “Events Without a Type”Events published without a type field are never validated, even with strict_types enabled. This allows channels to accept untyped events alongside typed, validated ones.
If you want to require every event to have a type, enforce that at the application level.
Schema Storage
Section titled “Schema Storage”The schema is stored in the channel’s config.types field. Strict enforcement is controlled by config.strict_types. You can inspect them via the channel detail endpoint:
curl https://your-server.workers.dev/api/v1/channels/market-signals{ "id": "market-signals", "name": "Market Signals", "is_public": true, "config": { "strict_types": true, "types": { "odds_shift": { "schema": { "type": "object", "properties": { "market": { "type": "string" }, "shift": { "type": "number" } }, "required": ["market", "shift"] } } } }}You can also set strict_types directly in a config file passed via --config:
{ "strict_types": true, "types": { "odds_shift": { "schema": { ... } } }}Recommendations
Section titled “Recommendations”- Define schemas early, even without strict types. They serve as documentation for consumers.
- Enable
strict_typesfor channels where data integrity matters (e.g., financial signals, structured alerts). - Use
requiredfields liberally to catch missing data at publish time. - Keep schemas focused. Each event type should validate only its own
datapayload.