-
Notifications
You must be signed in to change notification settings - Fork 0
API Documentation
This document describes the REST API endpoints for the AAS Generator service. The API enables creating and managing Asset Administration Shells (AAS), generating Submodels from structured data using templates, and managing templates/blueprints.
You can find an interactive version of this documentation in the Swagger UI at http://localhost:5064/swagger, which includes example requests and responses for each endpoint.
/api/v2/
Note: API v1 endpoints are deprecated. Use v2 endpoints for all new integrations.
All API endpoints require authentication. The API supports two authentication schemes:
-
API Key Authentication - Include the API key in the
X-API-KEYheader -
JWT Bearer Token - Include a valid JWT token in the
Authorization: Bearer <token>header
Configure authentication in appsettings.json:
- Set
Features__UseAuthenticationtotrueto enable authentication - Set
CustomerEndpointsSecurity__ApiKeyfor API key authentication - Configure
AzureAdorOpenIdsections for OAuth/OIDC authentication
Create new Asset Administration Shells with optional auto-generated Submodels.
Creates a new AAS for a given asset identifier. Optionally generates and attaches submodels if blueprint parameters are provided.
POST /api/v2/AasCreator/{assetIdShort}?overwrite={true|false}| Parameter | Type | Required | Description |
|---|---|---|---|
assetIdShort |
string | Yes | The short identifier for the asset (e.g., machine-001) |
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
overwrite |
boolean | No | false |
Controls what happens when an AAS with the generated ID already exists. See the detailed description below. |
The creation flow always builds and validates every requested submodel in memory first (no repository writes), then persists submodels, then creates the shell with all submodel references baked in. The overwrite flag only changes how a shell-id collision is handled when the shell is POSTed:
-
overwrite=false(default) — If a shell with the generatedaasIdalready exists, the repository returns409 Conflict. The endpoint does not touch the existing shell. Any submodels that were already POSTed in this request are rolled back (best-effort delete), and the endpoint responds with409 Conflict. Submodels that could not be deleted are listed inorphanedSubmodelIds. -
overwrite=true— If the shell does not yet exist, behavior is identical tooverwrite=false: the shell is created and the endpoint returns201 Created(nopreviousAas). If the shell already exists, the endpoint first GETs the existing shell (captured aspreviousAas), then PUTs the freshly built shell over it, and returns200 OKwith thepreviousAasfield.
Important semantics and trade-offs:
-
Overwrite is destructive for the shell, not the submodels. PUT replaces the shell document, so the old shell's own submodel references are dropped. The submodels they pointed to are not deleted — they are orphaned, and the caller decides what to do with them using the returned
previousAas. -
previousAasis point-in-time, not transactional. There is a small TOCTOU window between the GET (capture old shell) and the PUT (overwrite); a concurrent writer could change the shell in between.previousAasis best-effort. - The existing shell is never deleted. On any failure (submodel persistence or shell PUT), only submodels created during this request are rolled back; a pre-existing shell is left intact.
If you want to create an AAS with submodels, include a JSON body:
{
"blueprintsIds": ["blueprint-id-1", "blueprint-id-2"],
"data": {
"serialNumber": "SN-12345",
"manufacturer": "ACME Corp"
},
"language": "en",
"debug": false,
"globalAssetId": "https://example.com/assets/my-custom-asset-id"
}| Field | Type | Required | Description |
|---|---|---|---|
blueprintsIds |
string[] | No | List of blueprint IDs to use for submodel generation |
data |
object | No | JSON data to map into the submodel templates |
language |
string | No | Language code for MultiLanguageProperties (e.g., "en", "de") |
debug |
boolean | No | Include workflow logs in response (default: false). When enabled, the response includes a chronological log trail spanning all generation phases: blueprint retrieval, ID generation, data mapping, and repository persistence. |
globalAssetId |
string | No | Custom globalAssetId to use directly instead of generating one. If omitted, the globalAssetId is auto-generated from the configured prefix and ID generation rules. |
defaultThumbnail |
object | No | Default thumbnail for the AAS asset information. Matches the AAS v3 Resource schema: path (required) and contentType (optional). |
Success (201 Created) — when a new AAS is created. The previousAas field is absent.
Success (200 OK) — when an existing AAS is replaced (overwrite=true). The response includes the previousAas field capturing the shell as it was before the overwrite.
{
"assetId": "https://example.com/assets/machine-001",
"base64EncodedAssetId": "aHR0cHM6Ly9leGFtcGxlLmNvbS9hc3NldHMvbWFjaGluZS0wMDE=",
"aasId": "https://example.com/aas/machine-001",
"base64EncodedAasId": "aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvbWFjaGluZS0wMDE=",
"aasRepoUrl": "http://localhost:8081",
"submodelResults": [
{
"blueprintId": "nameplate-v1",
"success": true,
"message": "",
"generatedSubmodelId": "https://example.com/submodels/nameplate-001"
}
]
}Conflict (409 Conflict)
Returned when an AAS with the generated ID already exists and overwrite=false. The response body contains an error message and any orphanedSubmodelIds that could not be rolled back. See the overwrite section above for details.
Error (400 Bad Request)
Returned when submodel generation or input validation fails.
Generate and add Submodels to an existing AAS using the rules engine.
Takes blueprint templates and maps data from the provided JSON into them, then stores the generated submodels in the specified AAS.
POST /api/v2/DataIngest/{base64EncodedAasId}| Parameter | Type | Required | Description |
|---|---|---|---|
base64EncodedAasId |
string | Yes | The AAS ID encoded in Base64 URL format |
{
"blueprintsIds": ["contact-template-v1", "nameplate-template-v1"],
"data": {
"contacts": [
{"name": "John Doe", "email": "john@example.com"},
{"name": "Jane Smith", "email": "jane@example.com"}
],
"manufacturer": "ACME Corp",
"serialNumber": "SN-12345"
},
"language": "en",
"debug": false
}| Field | Type | Required | Description |
|---|---|---|---|
blueprintsIds |
string[] | Yes | List of blueprint IDs to generate submodels from |
data |
object | Yes | JSON data to map into templates. Use {} if no mapping is defined. |
language |
string | Yes | Language code for MultiLanguageProperties (e.g., "en", "de") |
debug |
boolean | No | Include workflow logs in response (default: false). When enabled, the response includes a chronological log trail spanning all generation phases: blueprint retrieval, ID generation, data mapping, and repository persistence. |
Success (200 OK) — with debug: true
{
"results": [
{
"blueprintId": "contact-template-v1",
"success": true,
"message": "",
"generatedSubmodelId": "https://example.com/submodels/contact-001",
"debugInfo": {
"logs": [
"INFO [2026-04-24T10:30:01.0000000Z] - Mapping blueprint contact-template-v1 to AAS aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvbXktbWFjaGluZQ==",
"INFO [2026-04-24T10:30:01.1000000Z] - Fetching blueprint: contact-template-v1",
"INFO [2026-04-24T10:30:01.2000000Z] - Blueprint fetched successfully",
"INFO [2026-04-24T10:30:01.2100000Z] - Extracted idShort: ContactInformation",
"INFO [2026-04-24T10:30:01.2200000Z] - Generating submodel ID",
"INFO [2026-04-24T10:30:01.3000000Z] - Submodel ID generated: https://example.com/submodels/contact-001",
"INFO [2026-04-24T10:30:01.3100000Z] - Starting data mapping",
"INFO [2026-04-24T10:30:01.3200000Z] - Started ValidateBlueprintStep",
"INFO [2026-04-24T10:30:01.3210000Z] - Finished ValidateBlueprintStep",
"INFO [2026-04-24T10:30:01.3220000Z] - Started DeepCloneBlueprintStep",
"INFO [2026-04-24T10:30:01.3230000Z] - Finished DeepCloneBlueprintStep",
"INFO [2026-04-24T10:30:01.3240000Z] - Started SetKindInstanceStep",
"INFO [2026-04-24T10:30:01.3250000Z] - Finished SetKindInstanceStep",
"INFO [2026-04-24T10:30:01.3260000Z] - Started DuplicateCollectionsStep",
"INFO [2026-04-24T10:30:01.3270000Z] - Finished DuplicateCollectionsStep",
"INFO [2026-04-24T10:30:01.3280000Z] - Started FilterElementsStep",
"INFO [2026-04-24T10:30:01.3290000Z] - Finished FilterElementsStep",
"INFO [2026-04-24T10:30:01.3300000Z] - Started DiscoverMappingDescriptorsStep",
"INFO [2026-04-24T10:30:01.3310000Z] - Finished DiscoverMappingDescriptorsStep",
"INFO [2026-04-24T10:30:01.3320000Z] - Started ResolveMappingExpressionsStep",
"INFO [2026-04-24T10:30:01.3330000Z] - Finished ResolveMappingExpressionsStep",
"INFO [2026-04-24T10:30:01.3340000Z] - Started AssignMappedFieldsStep",
"INFO [2026-04-24T10:30:01.3350000Z] - Finished AssignMappedFieldsStep",
"INFO [2026-04-24T10:30:01.3360000Z] - Started RemoveTopLevelQualifiersStep",
"INFO [2026-04-24T10:30:01.3370000Z] - Finished RemoveTopLevelQualifiersStep",
"INFO [2026-04-24T10:30:01.3380000Z] - Started ReplaceIdentificationStep",
"INFO [2026-04-24T10:30:01.3390000Z] - Finished ReplaceIdentificationStep",
"INFO [2026-04-24T10:30:01.3600000Z] - Data mapping completed",
"INFO [2026-04-24T10:30:02.0000000Z] - Posting submodel to repository",
"INFO [2026-04-24T10:30:02.1000000Z] - Adding submodel reference to shell",
"INFO [2026-04-24T10:30:02.2000000Z] - Submodel reference added to shell"
]
}
}
]
}Success (200 OK) — with debug: false (default)
{
"results": [
{
"blueprintId": "contact-template-v1",
"success": true,
"message": "",
"generatedSubmodelId": "https://example.com/submodels/contact-001"
}
]
}Note: When
debugisfalseor omitted, thedebugInfofield isnulland omitted from the response.
Error (400 Bad Request)
On error, errorInfo.logs always contains the workflow log trail up to (and including) the failure point, regardless of the debug flag:
{
"results": [
{
"blueprintId": "contact-template-v1",
"success": false,
"message": "Missing required data at path: contacts.name",
"generatedSubmodelId": "",
"errorInfo": {
"logs": [
"INFO [2026-04-24T10:30:01.0000000Z] - Mapping blueprint contact-template-v1 to AAS aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvbXktbWFjaGluZQ==",
"INFO [2026-04-24T10:30:01.1000000Z] - Fetching blueprint: contact-template-v1",
"INFO [2026-04-24T10:30:01.2000000Z] - Blueprint fetched successfully",
"INFO [2026-04-24T10:30:01.2200000Z] - Generating submodel ID",
"INFO [2026-04-24T10:30:01.3000000Z] - Submodel ID generated: https://example.com/submodels/contact-001",
"INFO [2026-04-24T10:30:01.3100000Z] - Starting data mapping",
"ERROR [2026-04-24T10:30:01.3200000Z] - Data mapping failed: Missing required data at path: contacts.name"
],
"qualifier": "SMT/MappingInfo",
"qualifierPath": "contacts.name"
}
}
]
}Error (500 Internal Server Error)
Returned when one or more blueprints fail structural validation at generation time. This happens when a stored blueprint predates the current validation rules or was modified outside the API and is now in an invalid state. The response contains the aggregated errors and the per-blueprint results:
{
"errors": [
{
"rule": "FieldNotApplicableToModelType",
"path": "ContactInformation > ContactName",
"message": "Field 'first' is not valid on model type 'Property'. Allowed fields: value, idShort, displayName."
}
],
"results": []
}Blueprints are customized Submodel templates with embedded mapping rules. They define how structured data is transformed into AAS Submodels.
Returns all available blueprints.
GET /api/v2/BlueprintsSuccess (200 OK)
Returns an array of blueprint Submodels in JSON format.
Returns a specific blueprint by its ID.
GET /api/v2/Blueprints/{base64EncodedBlueprintId}| Parameter | Type | Required | Description |
|---|---|---|---|
base64EncodedBlueprintId |
string | Yes | The blueprint ID encoded in Base64 URL format |
Success (200 OK)
Returns the blueprint Submodel in JSON format.
Error (400 Bad Request)
Blueprint not found or invalid ID.
Creates a new blueprint from a Submodel template. The blueprint is validated before being stored — if structural errors are detected, a 422 Unprocessable Entity response is returned listing all issues.
POST /api/v2/BlueprintsA complete Submodel JSON object with kind: "Template" and embedded Template Qualifiers for mapping rules.
{
"idShort": "ContactInformation",
"id": "https://example.com/blueprints/contact-v1",
"kind": "Template",
"semanticId": {
"type": "ExternalReference",
"keys": [{"type": "GlobalReference", "value": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations"}]
},
"submodelElements": [
{
"idShort": "ContactName",
"modelType": "Property",
"valueType": "xs:string",
"qualifiers": [
{
"type": "SMT/MappingInfo",
"value": "contact.name"
}
]
}
]
}Success (200 OK)
Returns the identifier of the newly created blueprint.
Validation Error (422 Unprocessable Entity)
Returned when the blueprint contains structural errors that would cause generation failures. All detected issues are returned at once.
{
"errors": [
{
"rule": "UnknownFieldName",
"path": "ContactInformation > ContactName",
"message": "Field 'foobar' is not a recognized mapping field. Allowed: value, idShort, displayName, multiLanguage, globalAssetId, entityType, first, second."
},
{
"rule": "InvalidJsonataSyntax",
"path": "ContactInformation > Email",
"message": "Invalid JSONata syntax: Expected ']' at position 6."
}
]
}Repository Error (4xx)
If validation passes but the BaSyx repository rejects the blueprint, the original status code and response body from the repository are relayed as-is.
Updates an existing blueprint. The same validation rules apply as for creation.
POST /api/v2/Blueprints/{submodelId}| Parameter | Type | Required | Description |
|---|---|---|---|
submodelId |
string | Yes | The ID of the blueprint to update |
The updated blueprint Submodel as JSON.
Success (204 No Content)
Validation Error (422 Unprocessable Entity)
Same format as Create Blueprint validation errors.
Deletes a blueprint.
DELETE /api/v2/Blueprints/{base64EncodedBlueprintId}| Parameter | Type | Required | Description |
|---|---|---|---|
base64EncodedBlueprintId |
string | Yes | The blueprint ID encoded in Base64 URL format |
- 204 No Content - Deletion successful
- 404 Not Found - Blueprint does not exist
- 400 Bad Request - Invalid ID format
Templates are standard Submodel templates from external sources or the templates AAS. Unlike blueprints, templates may be read-only if sourced from an external API.
Returns all available templates.
GET /api/v2/TemplatesSuccess (200 OK)
Returns an array of template Submodels.
Error (404 Not Found)
Templates could not be retrieved.
Creates a new template in the local templates AAS.
POST /api/v2/TemplatesNote: This endpoint is disabled when
SubmodelTemplatesApiUrlis configured. In that case, use the remote templates API.
A complete Submodel template as JSON.
- 204 No Content - Template created successfully
- 403 Forbidden - Remote templates API is configured; use that instead
- 400 Bad Request - Invalid template format
Generate standardized identifiers for AAS and Submodels.
Generates a complete set of IDs for creating a new AAS based on the provided asset identifier.
GET /api/v2/IdGenerator/aasIds/{assetIdShort}| Parameter | Type | Required | Description |
|---|---|---|---|
assetIdShort |
string | Yes | The short identifier for the asset |
Success (200 OK)
{
"assetId": "https://example.com/assets/machine-001",
"assetIdShort": "machine-001",
"aasId": "https://example.com/aas/machine-001",
"aasIdShort": "aas_machine-001"
}Generates a complete set of IDs with an auto-generated unique identifier.
GET /api/v2/IdGenerator/aasIds/Success (200 OK)
{
"assetId": "https://example.com/assets/xdtzq0F",
"assetIdShort": "xdtzq0F",
"aasId": "https://example.com/aas/xdtzq0F",
"aasIdShort": "aas_xdtzq0F"
}Generates the specified number of unique Submodel IDs.
GET /api/v2/IdGenerator/submodelIds/{count}| Parameter | Type | Required | Description |
|---|---|---|---|
count |
integer | Yes | Number of Submodel IDs to generate |
Success (200 OK)
[
"https://example.com/submodels/abc123",
"https://example.com/submodels/def456"
]Manage ID generation configuration settings.
Retrieves the current ID generation configuration settings.
GET /api/v2/ConfigurationSuccess (200 OK)
Returns the configuration settings as JSON.
Error (404 Not Found)
Configuration not found.
Applies a partial update to a specific ID generation setting.
PATCH /api/v2/Configuration?idShortPath={path}&value={value}| Parameter | Type | Required | Description |
|---|---|---|---|
idShortPath |
string | Yes | The path to the setting within the submodel elements |
value |
string | Yes | The new value to apply |
- 204 No Content - Update successful
- 404 Not Found - Setting not found
Blueprints use Template Qualifiers to define mapping rules. These qualifiers are embedded in Submodel elements.
{
"type": "SMT/<RuleType>",
"value": "<rule-configuration>"
}| Qualifier Type | Purpose | Example Value |
|---|---|---|
SMT/MappingInfo |
Map JSON path or Jsonata expression to element value |
"car.serialNo" or "$string(quantity)"
|
SMT/CollectionMappingInfo |
Duplicate elements for arrays | "car.contacts[*]" |
SMT/FilterMappingInfo |
Conditional element creation using boolean expressions | "car.engineType = 'electric'" |
SMT/Cardinality |
Define required/optional data |
"One" or "ZeroToOne"
|
Path mappings support both simple JSON paths and advanced Jsonata expressions:
Simple Paths:
-
data.field- Simple field access -
data.nested.field- Nested object access -
data.array[*]- Array iteration (for collections) -
data.array[0]- Specific array index
Jsonata Expressions (for SMT/MappingInfo):
-
$length(data.field)- String/array length -
$substring(data.field, 0, 3)- Extract substring -
data.field ~> $contains('text')- Check if contains (returns boolean) -
$string(data.number)- Convert number to string -
data.numA > data.numB- Numeric comparison (returns boolean) -
$uppercase($substring(data.code, 0, 3))- Chained operations
See Blueprint and Rules for comprehensive Jsonata function reference.
| Value | Behavior |
|---|---|
One |
Mandatory - throws error if data is missing |
ZeroToOne |
Optional - sets empty value if data is missing |
OneToMany |
Mandatory collection - at least one item required |
ZeroToMany |
Optional collection - empty array is allowed |
Note: Cardinality values are case-sensitive and validated at blueprint save time. Invalid values (e.g.
"one","Optional") will be rejected with a422response.
All endpoints return standard HTTP status codes:
| Status Code | Description |
|---|---|
| 200 OK | Request successful |
| 204 No Content | Request successful, no content returned |
| 400 Bad Request | Invalid request parameters or body |
| 401 Unauthorized | Missing or invalid authentication |
| 403 Forbidden | Insufficient permissions |
| 404 Not Found | Resource not found |
| 422 Unprocessable Entity | Blueprint validation failed (structural errors detected) |
| 500 Internal Server Error | Server-side error |
Returned by the Blueprint Create/Update endpoints when structural issues are detected:
{
"errors": [
{
"rule": "InvalidQualifierSegmentCount",
"path": "Nameplate > SerialNumber",
"message": "Qualifier type 'SMT/MappingInfo/value/extra' has 4 segments; expected at most 3."
}
]
}The rule field is a machine-readable enum. The path field uses the idShort breadcrumb trail of the element (e.g. ParentCollection > ChildElement), falling back to JSON pointer notation if idShort is unavailable.
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"detail": "Detailed error message"
}- Create a blueprint with mapping rules:
POST /api/v2/Blueprints
Content-Type: application/json
{
"idShort": "Nameplate",
"id": "https://example.com/blueprints/nameplate-v1",
"kind": "Template",
"submodelElements": [
{
"idShort": "ManufacturerName",
"modelType": "Property",
"valueType": "xs:string",
"qualifiers": [{"type": "SMT/MappingInfo", "value": "manufacturer.name"}]
},
{
"idShort": "SerialNumber",
"modelType": "Property",
"valueType": "xs:string",
"qualifiers": [{"type": "SMT/MappingInfo", "value": "serialNumber"}]
}
]
}- Create an AAS with auto-generated submodel:
POST /api/v2/AasCreator/my-machine
Content-Type: application/json
{
"blueprintsIds": ["https://example.com/blueprints/nameplate-v1"],
"data": {
"manufacturer": {"name": "ACME Corp"},
"serialNumber": "SN-12345"
},
"language": "en"
}If you already have an external asset identifier (e.g., from an ERP system), you can pass it directly as the globalAssetId:
POST /api/v2/AasCreator/my-machine
Content-Type: application/json
{
"globalAssetId": "https://erp.acme.com/assets/ASSET-2026-0042",
"blueprintsIds": ["https://example.com/blueprints/nameplate-v1"],
"data": {
"manufacturer": {"name": "ACME Corp"},
"serialNumber": "SN-12345"
},
"language": "en"
}The globalAssetId field is used as-is for the AAS assetInformation.globalAssetId. All other IDs (aasId, aasIdShort, assetIdShort) are still generated normally from the assetIdShort path parameter.
POST /api/v2/DataIngest/aHR0cHM6Ly9leGFtcGxlLmNvbS9hYXMvbXktbWFjaGluZQ==
Content-Type: application/json
{
"blueprintsIds": ["contact-template-v1"],
"data": {
"contacts": [
{"name": "Support", "email": "support@acme.com"}
]
},
"language": "en"
}Blueprint with collection mapping:
{
"idShort": "ContactPerson",
"modelType": "SubmodelElementCollection",
"qualifiers": [{"type": "SMT/CollectionMappingInfo", "value": "contacts[*]"}],
"value": [
{
"idShort": "Name",
"modelType": "Property",
"qualifiers": [{"type": "SMT/MappingInfo", "value": "contacts[*].name"}]
},
{
"idShort": "Email",
"modelType": "Property",
"qualifiers": [{"type": "SMT/MappingInfo", "value": "contacts[*].email"}]
}
]
}Input data:
{
"contacts": [
{"name": "John", "email": "john@example.com"},
{"name": "Jane", "email": "jane@example.com"}
]
}Generated output creates ContactPerson_0 and ContactPerson_1 collections with mapped values.
For interactive API exploration, access the Swagger UI at:
/swagger
This provides a complete OpenAPI specification with the ability to test endpoints directly.