Skip to main content

Inline Types

A type in Stateway is a named schema embedded inside a <bpmn:itemDefinition> element. Types are declared once at the top of the BPMN document and referenced from data objects, task inputs, and task outputs.

Available in BPMN XML only

These constructs (itemDefinition, dataObject/dataObjectReference, dataStore/dataStoreReference) are parsed only from BPMN 2.0 XML definitions. JSON/YAML process definitions express a subset and cannot declare typed data objects, data stores, or inline types. See the Processes guide for JSON/YAML format limitations.

Declaring a Type

All <bpmn:itemDefinition> elements go inside <bpmn:definitions>, before the process body:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions
xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:stateway="https://stateway.io/schema/bpmn/1.0"
targetNamespace="https://stateway.io/processes/my-process">

<bpmn:itemDefinition id="MyType" structureRef="..." />

<bpmn:process id="my-process" isExecutable="true">
<!-- process body -->
</bpmn:process>
</bpmn:definitions>

The structureRef attribute determines the type's flavor.

Flavor 1: XSD Primitives

For simple scalars, reference an XSD primitive. No schema body is needed:

<!-- A price field — must be a number -->
<bpmn:itemDefinition id="Price" structureRef="xsd:decimal" />

<!-- A boolean flag -->
<bpmn:itemDefinition id="IsUrgent" structureRef="xsd:boolean" />

<!-- A date-time string -->
<bpmn:itemDefinition id="DueDate" structureRef="xsd:dateTime" />

Supported XSD primitives:

structureRefValidates As
xsd:stringAny string
xsd:decimalAny number (integer or float)
xsd:intInteger
xsd:booleantrue or false
xsd:dateTimeISO 8601 date-time string
xsd:dateISO 8601 date string
xsd:timeISO 8601 time string
xsd:base64BinaryBase64-encoded string, up to MAX_BASE64_VARIABLE_BYTES (default 1 MB, decoded) — see Binary and File Data below

Flavor 2: Inline JSON Schema

For enumerations and objects, set structureRef="stateway:inline" and embed a JSON Schema (draft 2020-12) inside a <stateway:schema> element:

Enumeration

<bpmn:itemDefinition id="LoanStatus" structureRef="stateway:inline">
<bpmn:extensionElements>
<stateway:schema kind="enum"><![CDATA[
{
"type": "string",
"enum": ["draft", "submitted", "in_review", "approved", "rejected", "disbursed"]
}
]]></stateway:schema>
</bpmn:extensionElements>
</bpmn:itemDefinition>

Object

<bpmn:itemDefinition id="Applicant" structureRef="stateway:inline">
<bpmn:extensionElements>
<stateway:schema kind="object"><![CDATA[
{
"type": "object",
"required": ["fullName", "email", "documentId"],
"properties": {
"fullName": { "type": "string", "minLength": 2 },
"email": { "type": "string", "format": "email" },
"documentId": { "type": "string", "pattern": "^[0-9]{11}$" },
"phone": { "type": "string" }
},
"additionalProperties": false
}
]]></stateway:schema>
</bpmn:extensionElements>
</bpmn:itemDefinition>

Primitive with Constraints

<!-- A non-negative decimal with 2 decimal places max -->
<bpmn:itemDefinition id="Money" structureRef="stateway:inline">
<bpmn:extensionElements>
<stateway:schema kind="primitive"><![CDATA[
{
"type": "number",
"minimum": 0,
"multipleOf": 0.01
}
]]></stateway:schema>
</bpmn:extensionElements>
</bpmn:itemDefinition>

The kind attribute is a hint for documentation and form generation:

kindMeaning
enumFixed set of valid string (or scalar) values
objectStructured object with named fields
primitiveScalar with constraints beyond what the XSD primitive allows
referencePointer to another instance (used with DataStore)

Collections

Add isCollection="true" to wrap the schema in an array type. The item schema stays the same — the engine handles the array wrapping automatically:

<!-- A list of documents -->
<bpmn:itemDefinition id="DocumentList" structureRef="stateway:inline" isCollection="true">
<bpmn:extensionElements>
<stateway:schema kind="object"><![CDATA[
{
"type": "object",
"required": ["name", "url"],
"properties": {
"name": { "type": "string" },
"url": { "type": "string", "format": "uri" }
}
}
]]></stateway:schema>
</bpmn:extensionElements>
</bpmn:itemDefinition>

A variable typed as DocumentList must be a JSON array; each element must match the item schema.

Binary and File Data

There are two ways to get binary data into a process instance, and they're two different storage strategies — declaring one over the other doesn't turn on the other's behavior:

Base64 in a variable (xsd:base64Binary)Files API (stateway:file)
Where the data livesInside instance.variables, like any other valueIn object storage; the variable only holds a reference
Does the binary pass through the Stateway API?Yes — it's part of the JSON bodyNo — the client uploads directly to a pre-signed storage URL
Counts against the tenant's storage quota?NoYes
Download endpoint?No — read it back from the variable itselfYes — a dedicated redirect endpoint
Deletion leaves a tombstone?No — it's overwritten/removed like any variableYes — a file_ref_deleted tombstone replaces the value
Automatic retention/expiry?NoYes — files belonging to finished instances are eventually removed
Excluded from audit snapshots?Only if the variable name ends in _binary, _blob, or _base64Not applicable — no raw bytes ever reach a snapshot to begin with

Both structureRef values in this table are declarable and validated. But declaring the type is not what turns on any of the Files API behavior in the right column — quota accounting, the download endpoint, tombstones, and retention are all driven by the upload flow itself (POST /instances/:id/files → confirm), independent of whether the target variable has a declared type at all. What declaring stateway:file adds is:

  • Shape validation. The variable must hold either a live file reference (the file_ref object the Files API writes on confirm) or its deletion tombstone — anything else is rejected on assignment, the same way any other typed variable is. See The file_ref Variable Value for the exact fields.
  • A guard on the upload itself. Requesting an upload slot for a variable that's declared with an incompatible type (a different scalar type, or a stateway:file collection) is rejected with 422 VARIABLE_TYPE_MISMATCH before any bytes are transferred. A variable with no declared type (ad-hoc) still accepts uploads exactly as before.

An itemDefinition with a structureRef the parser doesn't recognize is still accepted without validation — this remains true for any token outside the two covered here (and outside stateway:inline/stateway:catalog/*, which have their own dedicated handling). Don't rely on an unrecognized structureRef to protect a variable; it silently validates nothing.

If you embed base64 data directly in a variable, xsd:base64Binary caps it at MAX_BASE64_VARIABLE_BYTES (default 1 MB, decoded) per variable, in addition to the overall 5 MB instance variables payload limit described in the File Variables guide. To keep it out of audit log snapshots, name the field with a _base64 suffix (the same convention used for _binary and _blob fields — see Audit Log).

For anything beyond a small embedded value, use the Files API instead.

Validation at Upload Time

When you POST /v1/definitions with a BPMN that contains itemDefinition elements, Stateway validates each schema immediately. If any schema is malformed, the upload is rejected with a descriptive error — invalid definitions never reach production.

Common rejection reasons:

CauseExample Error
structureRef="stateway:inline" with no <stateway:schema>itemDefinition "MyType": missing stateway:schema
Invalid JSON inside <stateway:schema>itemDefinition "MyType": schema is not valid JSON
Schema fails JSON Schema meta-validationitemDefinition "MyType": "minLength" requires integer
External $ref useditemDefinition "MyType": external $ref not allowed
structureRef="stateway:catalog/..."Not yet supported

Limits

To protect against abuse, the following limits apply (all configurable via environment variables):

LimitDefault
Max itemDefinition elements per document200
Max schema size per itemDefinition64 KB
Max schema nesting depth20 levels
External $ref URIsNot allowed

Complete Example

A self-contained BPMN with multiple type flavors:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions
xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:stateway="https://stateway.io/schema/bpmn/1.0"
targetNamespace="https://stateway.io/processes/loan-application">

<!-- Primitive XSD types — no schema body needed -->
<bpmn:itemDefinition id="Money" structureRef="xsd:decimal" />
<bpmn:itemDefinition id="DueDate" structureRef="xsd:date" />

<!-- Enum -->
<bpmn:itemDefinition id="LoanStatus" structureRef="stateway:inline">
<bpmn:extensionElements>
<stateway:schema kind="enum"><![CDATA[
{ "type": "string", "enum": ["draft", "approved", "rejected"] }
]]></stateway:schema>
</bpmn:extensionElements>
</bpmn:itemDefinition>

<!-- Object -->
<bpmn:itemDefinition id="Applicant" structureRef="stateway:inline">
<bpmn:extensionElements>
<stateway:schema kind="object"><![CDATA[
{
"type": "object",
"required": ["fullName", "email"],
"properties": {
"fullName": { "type": "string", "minLength": 2 },
"email": { "type": "string", "format": "email" }
}
}
]]></stateway:schema>
</bpmn:extensionElements>
</bpmn:itemDefinition>

<!-- Collection -->
<bpmn:itemDefinition id="Documents" structureRef="stateway:inline" isCollection="true">
<bpmn:extensionElements>
<stateway:schema kind="object"><![CDATA[
{
"type": "object",
"required": ["name", "url"],
"properties": {
"name": { "type": "string" },
"url": { "type": "string", "format": "uri" }
}
}
]]></stateway:schema>
</bpmn:extensionElements>
</bpmn:itemDefinition>

<bpmn:process id="loan-application" isExecutable="true">
<!-- process elements -->
</bpmn:process>
</bpmn:definitions>

This file is self-contained: export it, re-import it, and all type validation works identically — no external registry required.

tip

Enum values freeze with the process version. If you add a new valid status to LoanStatus, deploy a new version of the process definition. Running instances continue using the enum values from the version they were started with.