Early developmentNot everything described here has shipped yet.

Skip to content

Schema JSON Format ​

Schemas are stored as the JSON content of pages in the Schema namespace (7474), and returned and accepted by the Schema REST endpoints. For terms like Schema and Property Definition, see the Glossary. A machine-readable JSON Schema for this format is at schemaContentSchema.json; it checks structure only. Per-type value constraints (options, ranges, string formats, uniqueItems) are enforced server-side and reported as validation codes.

Top-Level Structure ​

json
{
  "description": "Optional description of the schema",
  "propertyDefinitions": {
    "<property-name>": { ... },
    "<property-name>": { ... }
  }
}
FieldTypeRequiredDescription
descriptionstringNoHuman-readable description of the schema
subjectsAreDependentbooleanNoWhether the Schema's Subjects are Dependent Subjects. Set when the Schema is created: a save that changes it is refused. Omitted when false.
propertyDefinitionsobjectYesMap of property names to property definition objects

Schema references ​

Wherever a Schema is named — a Subject's schema field, an entry of a relation property's targetSchemas — the value is a reference.

A string names a Schema of this wiki by its page title in the Schema namespace, without the namespace prefix. Any spelling of that title is stored as the title itself — person as Person, Person_name as Person name — so a reference read back can differ from the one written.

A Schema from another Source (ADR 023) is an object instead:

json
{ "source": "otherwiki", "name": "Company" }

source is a source key, written as for a Subject ID. Naming this wiki's own Source is the same reference as the bare name, and is stored as the bare name.

A reference to a Source this wiki does not have resolves to no Schema, reported as schema-not-found.

Property Definition ​

Every property definition carries the common fields below plus the type-specific fields for its type.

Common Fields ​

FieldTypeRequiredDefaultDescription
typestringYes-The property type. See Property Types.
descriptionstringNo""Human-readable description of the property
requiredboolean or objectNofalseWhether a value is required. Accepts a severity.
defaultvariesNonullDefault value when none is provided

Constraint severity ​

Every Constraint carries a severity of error or warning, which decides whether violating it can block a write. Write a Constraint either as the bare value, which keeps the default warning, or as an object carrying the severity:

json
{
  "type": "number",
  "required": { "severity": "error" },
  "minimum": 0,
  "maximum": { "value": 100, "severity": "error" }
}

Boolean Constraints (required, uniqueItems) take no value in the object form — writing the object at all implies true. multiple constrains when it is false, so its object form carries "value": false. Every other Constraint carries its value under value, including options, whose value is the options array.

The Constraints that accept a severity are required, multiple, minimum, maximum, minLength, maxLength, uniqueItems, and options. Only select, relation and monolingualText check multiple, so a severity on it is inert elsewhere. Severity is a Constraint concept, so it does not apply to Display Attributes such as precision, where it is discarded, nor to the shape-declaring fields type and targetSchemas, where it is rejected when the Schema is saved.

Canonical output emits the bare form whenever the severity is the default, so a Schema that sets no severities round-trips unchanged. Which violation each Constraint produces, and the fixed severities of the codes no Constraint backs, are covered in Validation codes.

Property Types ​

Text (text) ​

Plain text values.

FieldTypeDefaultDescription
multipleboolean or objectfalseAllow multiple values
uniqueItemsbooleanfalseReject duplicate values (only with multiple)
minLengthnumbernullMinimum trimmed length of each value
maxLengthnumbernullMaximum trimmed length of each value
json
{
  "type": "text",
  "multiple": true,
  "uniqueItems": true,
  "maxLength": 50
}

Text with language (monolingualText) ​

Text values that each carry the language they are in (ADR 34).

FieldTypeDefaultDescription
multipleboolean or objectfalseAllow multiple values
uniqueItemsbooleanfalseReject duplicates, comparing text and language together (only with multiple)
minLengthnumbernullMinimum trimmed length of each text
maxLengthnumbernullMaximum trimmed length of each text
json
{
  "type": "monolingualText",
  "multiple": true,
  "uniqueItems": true
}

URL (url) ​

URL values.

FieldTypeDefaultDescription
multipleboolean or objectfalseAllow multiple values
uniqueItemsbooleanfalseReject duplicate values (only with multiple)

Number (number) ​

Numeric values (integer or float).

FieldTypeDefaultDescription
precisionnumbernullNumber of decimal places for display
minimumnumbernullMinimum allowed value (inclusive)
maximumnumbernullMaximum allowed value (inclusive)
json
{
  "type": "number",
  "minimum": 0,
  "maximum": 100,
  "precision": 2
}

Select (select) ​

A fixed set of options the user picks from.

json
{
  "type": "select",
  "options": [
    { "id": "opt_draft",    "label": "Draft" },
    { "id": "opt_review",   "label": "Review" },
    { "id": "opt_approved", "label": "Approved" }
  ]
}
FieldTypeDefaultDescription
optionsSelectOption[][]The allowed options to choose from
multipleboolean or objectfalseAllow selecting more than one

Each SelectOption:

FieldTypeRequiredDescription
idstringYesStable identifier, unique within the property. Statements store this.
labelstringYesDisplay text, unique (case-insensitive, trimmed) within the property.

On write, a Statement value may be an option id, a label (case-insensitive, trimmed), or a { "id", "label" } object; a mismatched id/label is rejected. Reads and display resolve stored ids back to labels via the current Schema.

Relation (relation) ​

References to other Subjects.

FieldTypeRequiredDefaultDescription
targetSchemasarrayYes-One or more distinct references to the Schemas a target Subject may follow
multipleboolean or objectNofalseAllow multiple relations
json
{
  "type": "relation",
  "targetSchemas": [ "Person", "Group" ],
  "multiple": true
}

Either all target Schemas of a relation property declare their Subjects dependent or none does; a save that mixes them is refused. Target Schemas that do not exist, or that you may not read, do not count.

Boolean (boolean) ​

A true/false value. No type-specific fields; default may be true, false, or null (no default).

json
{
  "type": "boolean",
  "default": false
}

Date (date) ​

A calendar date, stored as a strict ISO 8601 YYYY-MM-DD string (no time or timezone; see invalid-date). minimum, maximum, and any default use the same format.

FieldTypeDefaultDescription
minimumstringnullEarliest allowed date
maximumstringnullLatest allowed date

DateTime (dateTime) ​

A date and time, stored as a strict ISO 8601 / xsd:dateTime string with an explicit timezone offset or Z (e.g. 2025-06-15T14:30:00Z; see invalid-datetime). minimum, maximum, and any default use the same format.

FieldTypeDefaultDescription
minimumstringnullEarliest allowed datetime
maximumstringnullLatest allowed datetime

REST API ​

GET /neowiki/v0/schema/{schemaName} wraps this format as { "schema": ... }, or { "schema": null } when the Schema does not exist or you may not read it.

PUT /neowiki/v0/schema/{schemaName} replaces the whole Schema without checking for changes made since you read it. It takes the Schema and an optional comment, used as the edit summary:

json
{ "schema": { "description": "...", "propertyDefinitions": { ... } }, "comment": "Add a Website property" }

It answers with { "schema": ... }, the saved Schema in the same form as GET. An invalid schema is rejected with 400, the reason in messageTranslations.

Complete Example ​

A "Company" schema with various property types:

json
{
  "description": "A business entity",
  "propertyDefinitions": {
    "Founded at": {
      "type": "number",
      "description": "Year the company was founded"
    },
    "Websites": {
      "type": "url",
      "multiple": true
    },
    "Main product": {
      "type": "relation",
      "targetSchemas": [ "Product" ]
    },
    "Products": {
      "type": "relation",
      "targetSchemas": [ "Product" ],
      "multiple": true
    },
    "Status": {
      "type": "select",
      "options": [
        { "id": "opt_active",    "label": "Active" },
        { "id": "opt_inactive",  "label": "Inactive" },
        { "id": "opt_acquired",  "label": "Acquired" },
        { "id": "opt_dissolved", "label": "Dissolved" }
      ],
      "required": true
    },
    "World domination progress": {
      "type": "number",
      "minimum": 0,
      "maximum": 100,
      "default": 0
    }
  }
}