# Registering Event Schemas

This guide shows how to **register JSON schemas** for events in EventSourcingDB using its HTTP API. You'll learn how to **associate a schema with an event type** and how **schema validation** is enforced.

## Registering a Schema

To validate incoming event data, you can **register a JSON schema** for a given event type. Each event type can have **exactly one schema**, and the schema applies to all events of that type – **past and future**.

To register a schema, send an HTTP request using **`POST`** to the **`/api/v1/register-event-schema`** endpoint:

```shell
curl \
  -i \
  -X POST \
  -H "authorization: Bearer <API_TOKEN>" \
  -H "content-type: application/json" \
  -d "{
    \"eventType\": \"io.eventsourcingdb.library.book-acquired\",
    \"schema\": \"{
      \"type\": \"object\",
      \"properties\": {
        \"title\": { \"type\": \"string\" },
        \"author\": {\"type\": \"string\"},
        \"isbn\": {\"type\": \"string\"}
      },
      \"required\": [
        \"title\",
        \"author\",
        \"isbn\"
      ],
      \"additionalProperties\": false
    }\"
  }" \
  http://localhost:3000/api/v1/register-event-schema
```

> **If Something Goes Wrong**
>
> If you receive an error stating that the event type already has a schema, keep in mind that a **schema cannot be modified or removed once registered**. You must **define a new event type** if you need a different schema.

If everything worked as expected, the server will reply with HTTP status code `200 OK` and the following response:

```json
{
  "specversion": "1.0",
  "id": "0",
  "time": "...",
  "source": "https://www.eventsourcingdb.io",
  "subject": "/api/v1/register-event-schema",
  "type": "io.eventsourcingdb.api.event-schema-registered",
  "datacontenttype": "application/json",
  "data": {
    "eventType": "io.eventsourcingdb.library.book-acquired",
    "schema": {
      "type": "object",
      "properties": {
        "title": { "type": "string" },
        "author": {"type": "string"},
        "isbn": {"type": "string"}
      },
      "required": [
        "title",
        "author",
        "isbn"
      ],
      "additionalProperties": false
    }
  }
}
```

### Schema Enforcement

Once a schema is registered for an event type:

- All *future* events of that type **must conform to the schema**.
- All *existing* events of that type **are validated retroactively**.
- If any existing event violates the schema, the schema cannot be registered.

This guarantees that all events of a given type – past and future – are schema-compliant.

Because of this strict enforcement, **schemas cannot be edited or deleted** after registration. If you need to change a schema, you must define a new event type. It is therefore strongly recommended to **include a version number in your event types**, such as:

- `io.eventsourcingdb.library.book-acquired.v1`
- `io.eventsourcingdb.library.book-acquired.v2`

> **Why Versioning Matters**
>
> If you **register a schema** for an event type and later need to add a required field, you can't update the existing schema. Instead, you must define a **new event type (e.g. with `.v2`)** and update your producers and consumers accordingly.

## Enforcing Known Event Types

By default, you can write events of **any** type, whether or not it has a registered schema – schemas are validated only where they exist. If you want to enforce a **closed set of known event types**, start the server with the **`--require-event-schemas`** flag:

```shell
./eventsourcingdb run [...] --require-event-schemas
```

With this enabled, the database **rejects any write whose event type has no registered schema**, so every event type must be registered before it can be written. This is an **advanced, opt-in setting** and is **off by default**, because turning it on rejects every type you have not registered a schema for yet.

Enforcement applies **only to new writes**: existing events are never touched, and enabling the flag does not retroactively validate the store. An event type that already exists but has no schema simply becomes **unwritable** until you register a schema for it.

To help you spot those, the server **logs a warning at startup** listing the existing event types that have no registered schema, so you know which ones still need one.

Enforcement also applies when **restoring a backup**: with the flag enabled, a backup may only be restored if **every event type in it has a schema**, otherwise the restore is rejected.

## Your Turn

Try **registering a schema** for one of your existing event types – for example:

- `io.eventsourcingdb.library.book-acquired`
- `io.eventsourcingdb.library.book-borrowed`

Then try the following:

- Try to write an event that **matches the schema** – it should be accepted.
- Try to write an event that **violates the schema** – it should be rejected.

You can also try to register a schema *after* writing a few events. If those events are valid, the schema will be accepted. Otherwise, you'll get a validation error and the schema will not be stored.
