Docs / EventSourcingDB / API / register-event-schema

register-event-schema

Registers a schema for an event type, which every event of the type has to match.

  • Route: POST /api/v2/data/register-event-schema
  • Category: data
  • Authentication: required, with the API token
  • Answer: a stream of NDJSON

An event type has at most one schema, which applies to all of its events, past and future, and which can be neither replaced nor removed once it is registered. So before it registers a schema, the database checks every event of the type that is stored already, and every one that is written while the check runs, and refuses the schema if one of them does not match; reads and writes go on meanwhile. For data of another shape, introduce a new event type. The tutorial Registering Event Schemas walks through it step by step.

Request#

The body is a JSON object, with the content type application/json:

Field Type Required Meaning
type string yes The event type to register the schema for, a reverse domain name such as io.eventsourcingdb.library.book-acquired.
schema object yes The JSON Schema that the data of the events of the type has to match, with "type": "object" at its top level. It may refer to its own parts with $ref, such as #/$defs/address, but not to other documents, nor back to a part that the reference lies within, as a schema that describes a tree does, nor to an anchor with $dynamicRef or $recursiveRef. It may reach at most 10,000 subschemas, counting a referenced one each time it is referenced, and each of its numbers may have at most 1,000 digits before and after its decimal point.

To register a schema for io.eventsourcingdb.library.book-acquired that requires a title and an author:

curl \
  -X POST \
  -H "authorization: Bearer secret" \
  -H "content-type: application/json" \
  -d '{"type":"io.eventsourcingdb.library.book-acquired","schema":{"type":"object","properties":{"title":{"type":"string"},"author":{"type":"string"}},"required":["title","author"]}}' \
  http://localhost:3000/api/v2/data/register-event-schema

Answer#

The answer is a stream of items, one per line. A registered schema is an event item:

Type Data When
event A CloudEvent of the type io.eventsourcingdb.api.event-schema-registered, whose data holds the type and the schema that were registered Once, when the schema is registered.
error code, description, and details When the schema cannot be registered, see Errors.
heartbeat empty While the registration takes a while, such as while it checks the stored events of the type, to keep the connection alive.
end empty Once, as the last item, when the stream ends cleanly.

Heartbeats and the end item work as on every stream of the API, see Streams. Either the event item or an error item comes, never both.

For an event type that has no schema yet, and no events, the request above is answered with:

{"type":"event","data":{"specversion":"1.0","id":"01a180c5-c8f9-7966-9f93-a68d5968243b","source":"https://www.eventsourcingdb.io","type":"io.eventsourcingdb.api.event-schema-registered","subject":"/api/v2/data/register-event-schema","time":"2026-10-28T04:30:08.121617Z","datacontenttype":"application/json","data":{"type":"io.eventsourcingdb.library.book-acquired","schema":{"properties":{"author":{"type":"string"},"title":{"type":"string"}},"required":["title","author"],"type":"object"}}}}
{"type":"end","data":{}}

Errors#

The registration reports these errors as an error item, followed by the end item. The event type and the schema are checked before the database is asked, so the first six are reported whatever the database holds, even in read-only mode:

  • event-type-missing: The request leaves out the event type, or sends it as an empty string.
  • event-type-malformed: The event type is not a reverse domain name, such as BookAcquired.
  • event-schema-missing: The request leaves out the schema.
  • event-schema-malformed: The schema is not a valid JSON Schema, for example because it refers to another document, or holds a number with more than 1,000 digits before or after its decimal point.
  • event-schema-not-object: The schema does not have "type": "object" at its top level.
  • event-schema-too-complex: The schema refers back to a part of itself, such as one that describes a tree, uses $dynamicRef or $recursiveRef to refer to an anchor, or reaches more than 10,000 subschemas, counting a referenced one each time it is referenced.
  • event-schema-already-registered: The event type has a schema already, even if it is the same one.
  • event-schema-violated: An event of the type, stored already or written during the check, does not match the schema.
  • store-read-only: The database is in read-only mode, which refuses registrations, since they are writes.
  • disk-full: The disk of the data directory is almost full, so the database refuses writes until there is room again.
  • restore-in-progress: A restore is running, which refuses writes until it has finished.
  • file-unreadable: A file of the store that the registration needs is damaged, such as an events file whose checksum no longer matches.
  • store-failed: The database has failed, after storing an earlier write or a restore failed, and refuses writes.
  • server-shutting-down: The server began to shut down after the stream had sent its first heartbeat. Before that, the server answers with 503 instead.

Status Codes#

Before the stream begins, the server answers with a status code other than 200 where it cannot take the request at all, as described in Errors:

  • 400: The content type of the body is not application/json, or the body is missing or no JSON object of the shape above, for example with a field the route does not know, such as eventType, which the v1 API took instead of type, with null as a value, or with a schema that is not a JSON object.
  • 401: The API token is missing or wrong.
  • 408: The body did not arrive in time.
  • 413: The body is larger than its limit.
  • 429: Too many requests were sent; the answer says when to try again.
  • 500: The server failed unexpectedly before the stream began. Once it has begun, the stream breaks off without its end item instead.
  • 503: The server is shutting down.