ORD Overlay
This specification is in alpha and subject to change.
The ORD Overlay is an optional ORD model extension that allows patching both ORD resource metadata and referenced resource definition files (e.g. OpenAPI, AsyncAPI, OData CSDL, MCP/A2A Agent Cards) without modifying the original source files.
{
"ordOverlay": "0.1",
"target": { "ordId": "sap.foo:apiResource:astronomy:v1", "definitionType": "openapi-v3" },
"patches": [
{
"action": "merge",
"selector": { "operation": "getConstellationByAbbreviation" },
"data": {
"summary": "Get constellation by IAU abbreviation",
"description": "Returns full details of a constellation by its IAU abbreviation (e.g. 'Ori' for Orion). Useful for star-chart lookups and astronomy education tools."
}
}
]
}
Distribution
Decision guidance for choosing a distribution mode is collected in the Appendix: ORD Configuration vs. Attached Resource Definition.
Via the ORD Configuration Endpoint
Overlays can be listed directly in the ORD Configuration Endpoint under openResourceDiscoveryV1.overlays.
This is the preferred approach for cross-cutting overlays that are not tied to a single resource, or when patching ORD resource metadata itself.
{
"openResourceDiscoveryV1": {
"overlays": [
{ "url": "/ord/overlays/my-api.overlay.json", "accessStrategies": [{ "type": "open" }] }
]
}
}
Attached to an ORD Resource
Overlays can also be attached directly to an API or Event resource as a resourceDefinitions entry with type ord:overlay:v1.
This keeps the overlay co-located with the resource it patches.
{
"resourceDefinitions": [
{ "type": "openapi-v3", "url": "/ord/metadata/my-api.oas3.json", "accessStrategies": [{ "type": "open" }] },
{ "type": "ord:overlay:v1", "url": "/ord/overlays/my-api.overlay.json", "accessStrategies": [{ "type": "open" }] }
]
}
Target Resolution
The optional target object narrows which document the overlay applies to.
When omitted, all patches in the file are context-free and each patch's selector alone identifies the element.
Key fields on target:
| Field | Purpose |
|---|---|
ordId | Identifies the ORD resource being patched (API, Event, Data Product, …). Selects the ORD resource metadata itself. |
url | Direct URL to the specific metadata definition file (e.g. an OpenAPI JSON file). |
definitionType | Declares the format of the file (e.g. openapi-v3, a2a-agent-card). Disambiguates when a resource has multiple definitions attached. |
Example of ambiguity: an OData API resource may expose both edmx and openapi-v3 definitions.
Provide definitionType and/or url to make the concrete patch target explicit.
For overlays that only patch ORD metadata via selector.ordId, target may be omitted.
Multiple resources can be patched in a single file using multiple patches with different selector ordId values.
Selectors
Each patch identifies the element to patch using exactly one selector.
Concept-level selectors are preferred over jsonPath because they are resilient to structural format changes
(e.g. OpenAPI 3.0 → 3.1, OData CSDL XML → JSON).
| Selector | Level | Supported formats |
|---|---|---|
ordId | Resource | ORD resource metadata |
operation | Operation | OpenAPI (openapi-v2/v3/v3.1+), MCP (MCP Server Card), A2A Agent Card (a2a-agent-card), OData (edmx, csdl-json) |
entityType | Entity type | OData (edmx, csdl-json), CSN Interop (sap-csn-interop-effective-v1) |
propertyType | Property | OData (edmx, csdl-json), CSN Interop (sap-csn-interop-effective-v1) |
jsonPath | Any location | Any JSON/YAML metadata file (generic fallback) |
The operation selector maps to different identifiers depending on the format:
- OpenAPI →
operationIdof an HTTP operation inpaths.{path}.{method} - MCP (any Specification ID) →
tools[].name - A2A Agent Card →
skills[].id - OData (
edmx,csdl-json) → Action or Function name, namespace-qualified (e.g.OData.Demo.Approval)
When definitionType is set on target, the format is known and the selector resolves unambiguously.
When definitionType is absent, the implementation SHOULD infer the format from the target document's content (e.g. the openapi field, $schema, or $kind markers).
Using the operation selector with a named format constant that has no operation support (e.g. asyncapi-v2) raises an error.
Patch Actions
Each patch specifies an action and a selector, plus an optional data value.
The full semantics of each action (update, merge, append, remove) are defined on the action field.
Key point for merge: arrays are appended, not replaced.
To fully replace an array, use two ordered patches — first remove the array, then merge the new value.
Validation
Overlays assume the target document is already valid for its native format. The merge tool does not fully re-validate target formats. After applying an overlay, validate the merged output with the corresponding format-specific tooling.
ORD Aggregator Expectations
An ORD Aggregator MUST apply overlays that patch ORD resource metadata when building its ORD Discovery API and related indexes. This is necessary so that ORD-level overlay changes are reflected in discovery responses, filtering, searching, and similar aggregator behavior.
An ORD Aggregator SHOULD enforce that overlay sources are permitted to patch the target metadata. Without such enforcement, consumers could be exposed to unauthorized metadata changes through overlay processing.
Overlay Document Metadata
Note on perspective: unlike its use in ORD Documents (which scopes transport),
perspective on an overlay declares where the patch should be applied — at system-type, system-version, or system-instance level.
See the field description for details.
Schema Definitions
- The root schema of the document is ORD Overlay
- The interface is available as JSON Schema: OrdOverlay.schema.json.
ORD Overlay
Type: Object($schema, ordOverlay, ordId, description, perspective, describedSystemType, describedSystemVersion, describedSystemInstance, visibility, target, patches)
| Property | Type | Description |
|---|---|---|
string | Optional URL to the ORD Overlay schema (defined as a JSON Schema). If provided, this enables code intelligence and validation in supported editors (like VSCode) and tools. JSON Schema Format: uri-referenceArray Item Allowed Values (extensible):
| |
string | Version of the ORD Overlay specification. Allowed Values:
Example Values:
| |
string | Optional ORD ID of this overlay document. MUST be provided if the ORD Overlay is published via ORD Configuration endpoint. Regex Pattern: ^([a-z0-9]+(?:[.][a-z0-9]+)*):(overlay):([a-zA-Z0-9._\-]+):(v0|v[1-9][0-9]*)$Maximum Length: 255Example Values:
| |
string | Optional description of the overlay document itself. Notated in CommonMark (Markdown). Minimum Length: 1Example Values:
| |
string | Overlay Perspective Overlay-specific perspective that scopes where this overlay should be applied. Use this together with describedSystemType, describedSystemVersion, and describedSystemInstanceto describe whether the overlay applies broadly to a system type, to one released system version, or only to a specific system instance. Allowed Values:
Example Values:
| |
Information on the system type this overlay describes. This object is identical to the ORD Document describedSystemType object.Its purpose is to link the overlay to the same system landscape model as ORD resources, if needed. This is the primary context object for perspective: system-type, and also the parent contextfor more specific system-version and system-instance overlays.Usually this is not necessary for static overlays if the patched resource is already selected via ORD ID. | ||
Information on the system version this overlay describes. This object is identical to the ORD Document describedSystemVersion object.Its purpose is to link the overlay to the same system landscape model as ORD resources, if needed. Use this when the overlay should only patch metadata for one specific released system version. Usually this is not necessary for static overlays if the patched resource is already selected via ORD ID. | ||
Information on the system instance this overlay describes. This object is identical to the ORD Document describedSystemInstance object.Its purpose is to link the overlay to the same system landscape model as ORD resources, if needed. Use this when the overlay should only patch metadata for one concrete tenant / runtime instance. Usually this is not necessary for static overlays if the patched resource is already selected via ORD ID. | ||
string | Overlay Visibility Controls which consumers can discover and access this overlay document. It does NOT control runtime access to the resources being patched — that is managed separately through authentication and authorization mechanisms. Use this to prevent exposing internal overlay enrichments to inappropriate consumer audiences. Allowed Values:
| |
Optional target context for this overlay. The target can reference an ORD resource or a referenced resource definition file. When target is present, at least one identifier (ordId, url, or correlationIds)MUST be provided so that consumers and tooling can determine what is being patched. ordId selects the ORD resource metadata itself.If patches are intended for a specific attached metadata definition file, ordId alone can be ambiguouswhen the resource exposes multiple definitions. In that case, use url and/or definitionType to clarify the intended file.Example: an OData API resource may provide both edmx and openapi-v3 definitions.Use definitionType and/or an explicit url to identify which one is patched.Exception: if all patches exclusively use selector.ordId, the patch selectors themselvesare sufficient to identify the target resources and target may be omitted entirely.Multiple resources can still be patched by defining multiple patches with different selector ordId values. | ||
Array<Overlay Patch> | Ordered sequence of patches to apply to the targeted resource(s). Patches are applied strictly in the order they are listed. If two patches target the same document element, both are applied in sequence — the later patch supersedes the earlier one. Array Constraint: MUST have at least 1 items |
Overlay Target
Optional context about the target being patched. The target can refer to an ORD resource or to a referenced resource definition file.
When this object is present, at least one of ordId, url, or correlationIds
MUST be provided so that consumers can identify what is being patched.
Exception: if all patches exclusively use selector.ordId selectors, target may be omitted entirely.
ordId targets the ORD resource metadata itself.
For patching a specific resource definition file of that resource, use url and/or definitionType
to disambiguate.
Example: one OData API resource can have both edmx and openapi-v3 definitions attached.
In such cases, provide definitionType and/or url to make the concrete patch target explicit.
Multiple identifiers, if provided, are treated as all pointing to the same resource.
Type: Object(ordId, url, correlationIds, definitionType)
| Property | Type | Description |
|---|---|---|
string | ORD ID of the target being patched (e.g. an API Resource, Event Resource, Data Product). MUST be a valid ORD ID. Regex Pattern: ^([a-z0-9]+(?:[.][a-z0-9]+)*):([a-zA-Z0-9.\-]+):([a-zA-Z0-9.\-]+):(v0|v[1-9][0-9]*)$Maximum Length: 255Example Values:
| |
string | URL or URI pointing directly to the file being patched. This is typically a resource definition file (e.g. OpenAPI, AsyncAPI, OData CSDL), but can also point to any JSON/YAML-based target document. JSON Schema Format: uri-referenceExample Values:
| |
Array<string> | Correlation IDs referencing the target resource in external registries or systems of record. Reuses the ORD correlation ID format: namespace:type:localId.All listed IDs are treated as pointing to the same resource. Array Constraint: MUST have at least 1 items Array Item Regex Pattern: ^([a-z0-9]+(?:[.][a-z0-9]+)*):([a-zA-Z0-9.\-\/]+):([a-zA-Z0-9.\-\/]+)$Example Values:
| |
string | Overlay Definition Type Optional, but RECOMMENDED type of the target definition being patched. If provided, this SHOULD match the type of the referenced metadata definition(as used in API/Event/Capability resource definitions). This is especially useful when ordId resolves to a resource with multiple attached definitions.This can be used to disambiguate how selectors are interpreted for the target. MUST be either: - any valid Specification ID, or - one of the pre-defined values reused from: - API Resource Definition type- Event Resource Definition type- Capability Definition typeThe literal value custom is deprecated for definitionType and MUST NOT be used.In such cases, use a concrete Specification ID instead. Array Item Allowed Values (extensible):
Example Values:
|
Overlay Patch
A single patch action to apply to the element identified by the selector.
Type: Object(description, action, selector, data, tags, meta)
| Property | Type | Description |
|---|---|---|
string | Optional human-readable note explaining the purpose or rationale of this individual patch. This field is purely informational and has no effect on patch application. Typical use-cases: - Reviewer / audit notes explaining why a particular element is being modified. - Commit-message style annotations generated by AI tooling (e.g. "Enriched summary for GetUser operation"). - References to tickets or decisions that motivated the change. Maps 1:1 to the actions[].description field in theOpenAPI Overlay spec, enabling lossless round-trip conversion between OpenAPI overlays and ORD overlays. Example Values:
| |
string | The patch operation to perform on the selected element: - update: Replace the selected element entirely with data.- append:- When data is a string: append it to the selected string value.Only valid when the selected element is a text/string field. - When data is an object: recursively append each string property in datato the corresponding string field in the selected object. Nested objects are traversed; arrays in data are appended to matching arrays.Throws an error if a string in data targets a non-string field in the target.- Useful to extend existing descriptions, summaries, or other text fields without replacing them entirely. - remove:- data: {} (empty object): remove the selected element from the document entirely.- data with null-valued properties: remove only those fields (recursively).Nested null values remove nested fields as well(JSON Merge Patch-style delete semantics). Example for partial removal: data: { "foo": { "bar": null } } removes only foo.bar inside the selected element.To remove the entire selected element, use data: {}.- merge:- objects are deep-merged recursively. - scalar values are overwritten by the value from data.- arrays are appended (new array items are added after existing items). - existing object properties not mentioned in data are preserved.To fully replace an array, use two ordered patches: 1. remove the array at the selected location.2. merge the new array content.Allowed Values:
| |
Identifies the element in the target to patch. Exactly one selector type is used per patch. The selector object uses one explicit key: - ordId: resource level - targets an ORD resource (API, Event, Data Product, ...)- operation: operation level - targets an operation (OpenAPI: operationId, MCP: tool name, OData: Action/Function name)- entityType: entity type level - targets an OData EntityType or CSN entity definition by name- propertyType: property type level - targets a property/element on an OData EntityType/ComplexType or a CSN entity element- jsonPath: generic fallback - targets any location in a JSON/YAML-based target document by pathPrefer concept-level selectors (operation, entityType, propertyType) over jsonPath where possible, as they are resilient to structural changes in the target format. | ||
The value to be used together with patch actions: - with action: append:- string value appended to selected text field - with action: merge:- objects are deep-merged recursively - scalar values overwrite existing values - arrays are appended to existing arrays - with action: update, it replaces the selected element entirely- with action: remove:- {} (empty object): the selected element is removed entirely- object with null-valued properties: only those fields are deleted (recursively, including nested fields; JSON Merge Patch-style delete semantics) To fully replace an existing array, use two ordered patches: 1. remove the array 2. merge the new array value For OData targets ( edmx, csdl-json), the value MUST be expressed in CSDL JSONannotation format. Annotation keys use the @TermName convention:e.g. { "@Core.Description": "...", "@Core.Revisions": [...] }.When the target is EDMX XML, the merge implementation converts this to <Annotation> elements.See: https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html For CSN Interop targets ( sap-csn-interop-effective-v1), the value is plain CSN JSONmerged directly into the matched entity definition or element object. Use the CSN doc field for human-readable descriptions, and @AnnotationName keysfor vocabulary annotations (e.g. @EndUserText.label, @Semantics.text).See: https://sap.github.io/csn-interop-specification/ This is a free-form value whose structure depends on the target being patched. null as a standalone patch value is not supported outside remove masks.To delete an element, use action: remove with data: {}. | ||
Array<string> | String labels associated with the patched element. Useful for classification, domain tagging, and filtering in registries or tooling. These are purely informational and have no effect on patch application or on the target document. Array Constraint: MUST have at least 1 items Example Values:
| |
Optional arbitrary metadata associated with the patched element for use by overlay consumers, tooling, and registries. The contents of this block are never applied to the target document — they are strictly out-of-band and ignored by the patch merge process. Use this to carry information that enrichment sources associate with a specific element but that has no standard representation in the target metadata format. This is an open/extensible object — any properties are allowed. |
Overlay Patch Meta
Optional arbitrary metadata associated with the patched element for use by overlay consumers, tooling, and registries. The contents of this block are never applied to the target document — they are strictly out-of-band and ignored by the patch merge process.
Use this to carry information that enrichment sources associate with a specific element but that has no standard representation in the target metadata format.
This is an open/extensible object — any properties are allowed.
Overlay Selector
Identifies the element in the target to patch. Exactly one selector type is used per patch. The selector object uses one explicit key:
ordId: resource level - targets an ORD resource (API, Event, Data Product, ...)operation: operation level - targets an operation (OpenAPI: operationId, MCP: tool name, OData: Action/Function name)entityType: entity type level - targets an OData EntityType or CSN entity definition by namepropertyType: property type level - targets a property/element on an OData EntityType/ComplexType or a CSN entity elementjsonPath: generic fallback - targets any location in a JSON/YAML-based target document by path
Prefer concept-level selectors (operation, entityType, propertyType) over jsonPath where possible, as they are resilient to structural changes in the target format.
One of the following:
Overlay Selector By JsonPath | Overlay Selector By ORD ID | Overlay Selector By Operation | Overlay Selector By Entity Type | Overlay Selector By Property Type | Overlay Selector By Entity Set | Overlay Selector By Namespace | Overlay Selector By Parameter | Overlay Selector By Return Type
Example Values:
{
"ordId": "sap.foo:apiResource:astronomy:v1"
}
{
"operation": "getConstellationByAbbreviation"
}
{
"operation": "OData.Demo.Approval"
}
{
"operation": "dispute-case-resolution"
}
{
"entityType": "OData.Demo.Customer"
}
{
"entityType": "AirlineService.Airline"
}
{
"propertyType": "BirthDate",
"entityType": "OData.Demo.Customer"
}
{
"propertyType": "AirlineID",
"entityType": "AirlineService.Airline"
}
{
"jsonPath": "$.info.description"
}
{
"jsonPath": "$.paths['/constellations'].get"
}
Overlay Selector By JsonPath
Type: Object(jsonPath)
| Property | Type | Description |
|---|---|---|
string | JSONPath expression targeting any location in a JSON/YAML-based target document. MUST start with $.This is the generic structural fallback selector, supported for all JSON/YAML-based formats: - openapi-v2, openapi-v3, openapi-v3.1+: targets any node in the OpenAPI document.- a2a-agent-card: targets any node in the A2A Agent Card JSON document.- csdl-json: targets any node in the OData CSDL JSON document.- MCP (any Specification ID): targets any node in the MCP-compatible JSON/YAML tool metadata. Use concept-level selectors ( operation, entityType, etc.) when available, as they areresilient to structural differences between format versions. Reserve jsonPath for caseswhere no concept-level selector covers the target location. Regex Pattern: ^\$Minimum Length: 1Example Values:
|
Overlay Selector By ORD ID
Type: Object(ordId)
| Property | Type | Description |
|---|---|---|
string | ORD ID targeting an ORD resource (API, Event, Data Product, ...) in an ORD document. MUST be a valid ORD ID. Supported metadata formats: - ORD document (no specific definitionType): locates the ORD resource object whoseordId field matches this value. The resource type (apiResource, eventResource,dataProduct, etc.) is derived from the ORD ID namespace and is not required in the selector. Use this selector when patching ORD resource metadata itself (e.g. title, description, visibility, tags). For patching the technical API definition file that the resource references, apply the overlay to that definition file directly using its own selectors. Regex Pattern: ^([a-z0-9]+(?:[.][a-z0-9]+)*):([a-zA-Z0-9.\-]+):([a-zA-Z0-9.\-]+):(v0|v[1-9][0-9]*)$Example Values:
|
Overlay Selector By Operation
Type: Object(operation)
| Property | Type | Description |
|---|---|---|
string | Concept-level operation identifier. Supported mappings by format: - OpenAPI ( openapi-v2, openapi-v3, openapi-v3.1+): maps to the operationId field onan HTTP operation inside paths.{path}.{method}.- MCP (any Specification ID other than a2a-agent-card): maps to tools[].name.See: https://modelcontextprotocol.io/specification/2025-11-25/schema#tool-name - A2A Agent Card ( a2a-agent-card): maps to skills[].id.See: https://google.github.io/A2A/specification/#agentskill-object - OData ( edmx, csdl-json): maps to the Action or Function name at Schema level.MUST use the namespace-qualified name (e.g. OData.Demo.Approval) to be unambiguous.For OData v2 edmx targets: also searches FunctionImport elements in EntityContainerwhen no Schema-level Action/Function matches the name. For bound operations overloaded on multiple entity types, use jsonPath as a fallbackto target the specific overload. When definitionType is set on target, the format is known and the selector resolves unambiguously.When definitionType is absent, the implementation SHOULD infer the format from the targetdocument's content (e.g. the openapi field, $schema, or $kind markers).Minimum Length: 1Example Values:
|
Overlay Selector By Entity Type
Type: Object(entityType)
| Property | Type | Description |
|---|---|---|
string | Concept-level entity or enum type identifier. Supported metadata formats: - edmx (OData v2/v4 CSDL XML): targets EntityType, ComplexType, or EnumType elementsdeclared in the Schema. MUST use the namespace-qualified name (e.g. OData.Demo.Customer).For EntitySet-level patching (Capabilities annotations), use the entitySet selector instead.- csdl-json (OData v4 CSDL JSON): same name resolution as edmx. Resolves elementswith $Kind equal to EntityType, ComplexType, or EnumType.- sap-csn-interop-effective-v1 (CSN Interop): targets a definitions entry by itsfully qualified key (e.g. AirlineService.Airline). In CSN Interop the key is alwaysfully qualified, so the fully qualified form MUST be used. When targeting an EnumType to patch its members individually, use this selector as the entityType context within a propertyType selector.Minimum Length: 1Example Values:
|
Overlay Selector By Property Type
Type: Object(propertyType, entityType)
| Property | Type | Description |
|---|---|---|
string | Concept-level property, navigation property, or enum member identifier. Supported metadata formats: - edmx (OData v2/v4 CSDL XML): targets a Property or NavigationProperty on an EntityTypeor ComplexType; or a Member on an EnumType. Use the unqualified name (e.g. BirthDate).- csdl-json (OData v4 CSDL JSON): same resolution as edmx. Targets non-$-prefixed keyson the matched EntityType, ComplexType, or EnumType object. - sap-csn-interop-effective-v1 (CSN Interop): targets an entry in the elements map ofthe matched entity definition. Use the element name as defined (e.g. AirlineID, Name).entityType MUST always accompany this field to unambiguously identify the owning type.Property names are unqualified and frequently reused across entity types (e.g. Name,Description, CreatedAt), so propertyType alone is not a reliable unique selector.To patch an enum member, set entityType to the qualified EnumType name andpropertyType to the unqualified member name.Minimum Length: 1Example Values:
| |
string | Required entity type, complex type, or enum type context for the selected property or member. Because property and member names are unqualified and commonly repeated across types (e.g. Name, Description, CreatedAt), entityType is mandatory to ensurethe selector is unambiguous and stable across schema evolution. - For OData EntityType/ComplexType: the namespace-qualified name (e.g. OData.Demo.Customer).- For OData EnumType: the namespace-qualified EnumType name (e.g. OData.Demo.OrderStatus).- For CSN Interop: the fully qualified definitions key of the containing entity(e.g. AirlineService.Airline).Minimum Length: 1Example Values:
|
Overlay Selector By Entity Set
Type: Object(entitySet)
| Property | Type | Description |
|---|---|---|
string | Concept-level entity set identifier. Supported metadata formats: - edmx (OData v2/v4 CSDL XML): targets an EntitySet element inside EntityContainer.May use the unqualified name (e.g. Customers) or namespace-prefixed name.- csdl-json (OData v4 CSDL JSON): targets a key with $Collection: true inside theEntityContainer object in the namespace. Use entitySet when you need to patch EntityContainer-bound metadata such asCapabilities annotations (InsertRestrictions, UpdateRestrictions, etc.). For patching the EntityType structure (Properties, NavigationProperties), use entityType.Minimum Length: 1Example Values:
|
Overlay Selector By Namespace
Type: Object(namespace)
| Property | Type | Description |
|---|---|---|
string | Concept-level OData schema/namespace selector. Supported metadata formats: - edmx (OData v2/v4 CSDL XML): targets the <Schema Namespace="..."> element.Use the namespace value exactly as declared (e.g. com.example.OrderService).- csdl-json (OData v4 CSDL JSON): targets the namespace-level object (the non-$-prefixedkey in the CSDL JSON document that matches the namespace value). Use this selector for service/schema-level annotations such as @Core.Description and@Core.LongDescription on the OData service as a whole.Minimum Length: 1Example Values:
|
Overlay Selector By Parameter
Type: Object(parameter, operation)
| Property | Type | Description |
|---|---|---|
string | Concept-level parameter name. Supported metadata formats: - edmx (OData v2/v4 CSDL XML): targets a <Parameter Name="..."> child element onan Action, Function, or FunctionImport. Use the unqualified parameter name. - csdl-json (OData v4 CSDL JSON): targets an entry in the $Parameter array of anAction/Function overload whose $Name matches.- OpenAPI ( openapi-v2, openapi-v3, openapi-v3.1+): targets an entry in theparameters array of the operation identified by operation (operationId), matchingby the parameter name field.operation MUST always accompany this field to unambiguously identify the owning operation.Minimum Length: 1Example Values:
| |
string | Required operation context for the selected parameter. - For OData: the namespace-qualified Action, Function, or FunctionImport name. - For OpenAPI: the operationId of the HTTP operation.Minimum Length: 1Example Values:
|
Overlay Selector By Return Type
Type: Object(returnType, operation)
| Property | Type | Description |
|---|---|---|
boolean | Flag indicating that the return type of the specified operation is the target. MUST be true. Use operation to identify the owning operation.Supported metadata formats: - edmx (OData v2/v4 CSDL XML): targets the <ReturnType> child element of thematched Action or Function element. - csdl-json (OData v4 CSDL JSON): targets the $ReturnType object inside the matchedAction/Function overload array entry. Constant Value: true | |
string | Namespace-qualified Action or Function name whose ReturnType is targeted. - For edmx: the namespace-qualified name of the Action or Function (e.g. com.example.Svc.TerminateEmployee).- For csdl-json: the namespace-qualified name looked up in the Namespace object.Minimum Length: 1Example Values:
|
Overlay Patch Value
The value to be used together with patch actions:
- with
action: append:- string value appended to selected text field
- with
action: merge:- objects are deep-merged recursively
- scalar values overwrite existing values
- arrays are appended to existing arrays
- with
action: update, it replaces the selected element entirely - with
action: remove:{}(empty object): the selected element is removed entirely- object with null-valued properties: only those fields are deleted (recursively, including nested fields; JSON Merge Patch-style delete semantics)
To fully replace an existing array, use two ordered patches:
- remove the array
- merge the new array value
For OData targets (edmx, csdl-json), the value MUST be expressed in CSDL JSON
annotation format. Annotation keys use the @TermName convention:
e.g. { "@Core.Description": "...", "@Core.Revisions": [...] }.
When the target is EDMX XML, the merge implementation converts this to <Annotation> elements.
See: https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/odata-csdl-json-v4.01.html
For CSN Interop targets (sap-csn-interop-effective-v1), the value is plain CSN JSON
merged directly into the matched entity definition or element object.
Use the CSN doc field for human-readable descriptions, and @AnnotationName keys
for vocabulary annotations (e.g. @EndUserText.label, @Semantics.text).
See: https://sap.github.io/csn-interop-specification/
This is a free-form value whose structure depends on the target being patched.
null as a standalone patch value is not supported outside remove masks.
To delete an element, use action: remove with data: {}.
Type: object,array,string,number,boolean,null
Overlay System Instance
A system instance is a concrete, running instance of a system type.
This object is identical to the ORD Document describedSystemInstance object.
Its purpose is to link the overlay to the same system landscape model as ORD resources, if needed. Usually this is not necessary for static overlays if the patched resource is already selected via ORD ID.
Type: Object(baseUrl, localId, correlationIds)
| Property | Type | Description |
|---|---|---|
string | Optional base URL of the system instance. By providing the base URL, relative URLs in the overlay are resolved relative to it. JSON Schema Format: uri-referenceRegex Pattern: ^http[s]?:\/\/[^:\/\s]+\.[^:\/\s\.]+(:\d+)?(\/[a-zA-Z0-9-\._~]+)*$Example Values:
| |
string | Optional local ID for the system instance (usually tenant ID), as known by the described system. Maximum Length: 255Example Values:
| |
Array<string> | Correlation IDs for linking this system instance to external systems of record. Array Constraint: MUST have at least 1 items Array Item Regex Pattern: ^([a-z0-9]+(?:[.][a-z0-9]+)*):([a-zA-Z0-9.\-\/]+):([a-zA-Z0-9.\-\/]+)$Example Values:
|
Overlay System Type
A system type is the abstract type of an application or service, from operational perspective.
This object is identical to the ORD Document describedSystemType object.
Its purpose is to link the overlay to the same system landscape model as ORD resources, if needed. Usually this is not necessary for static overlays if the patched resource is already selected via ORD ID.
Type: Object(systemNamespace, correlationIds)
| Property | Type | Description |
|---|---|---|
string | The system namespace is a unique identifier for the system type. Regex Pattern: ^[a-z0-9]+(?:[.][a-z0-9]+){1}$Maximum Length: 32Example Values:
| |
Array<string> | Correlation IDs for linking this system type to external systems of record. Array Constraint: MUST have at least 1 items Array Item Regex Pattern: ^([a-z0-9]+(?:[.][a-z0-9]+)*):([a-zA-Z0-9.\-\/]+):([a-zA-Z0-9.\-\/]+)$Example Values:
|
Overlay System Version
A system version describes a version/release of the system.
This object is identical to the ORD Document describedSystemVersion object.
Its purpose is to link the overlay to the same system landscape model as ORD resources, if needed. Usually this is not necessary for static overlays if the patched resource is already selected via ORD ID.
Type: Object(version, title, correlationIds)
| Property | Type | Description |
|---|---|---|
string | The version of the system instance (run-time) or the version of the described system-version perspective. It MUST follow the Semantic Versioning 2.0.0 standard. Regex Pattern: ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$Example Values:
| |
string | Human-readable title of the system version. Minimum Length: 1Maximum Length: 255Example Values:
| |
Array<string> | Correlation IDs for linking this system version to external systems of record. Array Constraint: MUST have at least 1 items Array Item Regex Pattern: ^([a-z0-9]+(?:[.][a-z0-9]+)*):([a-zA-Z0-9.\-\/]+):([a-zA-Z0-9.\-\/]+)$Example Values:
|
Appendix
Deep Dive: Overlays vs. Resource Definition Visibility
When additional metadata should only be visible to a narrower audience, two main approaches exist:
- publish a separate overlay that patches the target metadata for that audience
- publish multiple resource definitions of the same resource with different
API Resource Definition.visibilitysettings
These approaches solve different problems:
- resource-definition visibility controls who can access a concrete published definition file
- overlays add another metadata layer without modifying the original source
Prefer overlays when
- the enrichment is owned by a different team than the team publishing the base resource definition
- the enrichment has a different lifecycle, approval workflow, or release cadence
- the enrichment should be optional and separable from the original source
- multiple parallel enrichments may exist for different consumers or use cases
- the original source format should remain untouched, for example because it is generated elsewhere or mirrored from another system
Prefer multiple resource definitions with different visibility when
- the same producer team owns both the public and internal metadata
- the enriched information is part of the authoritative source and should not drift from it
- full consumer compatibility is required without assuming overlay support
- the difference is primarily "what full definition should this audience receive?" rather than "what extra layer should be applied afterward?"
- the provider already has a reliable publishing pipeline for separate public/internal definition artifacts
Main tradeoff
- overlays improve separation of concerns, but they add a second source of truth and may create ordering, sync, and provenance questions
- duplicated resource definitions reduce consumer complexity and stay self-contained, but they increase publisher-side duplication and consistency obligations
- both approaches can be combined: a narrower-visibility definition may still be enriched further via overlay
Rule of thumb:
- use resource-definition visibility for authoritative producer-owned variants
- use overlays for additive, externally managed, or use-case-specific enrichment layers
Deep Dive: ORD Configuration vs. Attached Resource Definition
Overlays can be distributed either through the ORD Configuration endpoint or by attaching them as ord:overlay:v1 resource definitions to a resource.
Those options are not interchangeable in practice, because they imply different ownership and publication models.
The strongest discriminator is ownership: if the overlay is created by a different ORD Provider than the one describing the target resource, there is in practice no way to attach that overlay as a resource definition of the foreign resource. In that case, ORD Configuration is the viable distribution mechanism.
Prefer ORD Configuration when
- the overlay is created by someone other than the original resource provider
- the overlay patches ORD resource metadata itself rather than only one attached definition file
- the overlay is cross-cutting and applies to multiple resources
- the overlay should be published independently from the lifecycle of one concrete API or Event resource
- the overlay provider needs its own publication channel and cannot modify the target resource entry
Prefer attaching as a resource definition when
- the same ORD Provider owns both the target resource and the overlay
- the overlay belongs to the resource as part of the producer-owned metadata package
- consumers should discover the overlay directly next to the resource definition it patches
- the overlay lifecycle is tightly coupled to one specific API or Event resource
- the producer wants the co-location to be explicit in the resource metadata itself
Main tradeoff
- ORD Configuration is more flexible for independent publishers, cross-resource overlays, and separate release cycles
- attached resource definitions are easier to understand when the overlay is just another producer-owned artifact of the same resource
- ORD Configuration makes provenance and authorization more important, because overlays may come from outside the original resource provider
- attached overlays reduce indirection, but only work when the publisher controls the target resource entry
Rule of thumb:
- use attached resource definitions for producer-owned, resource-local overlays
- use ORD Configuration for externally managed, cross-resource, or ORD-level overlays
Open TODOs
Aggregator behavior and compatibility:
- Decide how to indicate use-case-specific overlays when multiple overlays exist for the same target.
OData selectors:
- Define the implementation roadmap for
entityTypeandpropertyTypeselector support in the reference merge library. - Decide whether OData overlays should be restricted to annotation-only patches (i.e.
datakeys MUST follow the@TermNameconvention). In practice, all meaningful OData enrichments are vocabulary annotations, and allowing arbitrary structural changes could produce invalid CSDL output. Restricting to annotations would also make the patch intent more explicit and aid validation. Note: OData patching/merging almost certainly operates at the annotation level — but it is not entirely clear whetherremoveor structural changes to non-annotation elements should also be supported (e.g. deprecating or removing an operation from a CSDL description). - Decide whether the
entityTypeselector should target only the EntityType/ComplexType definition, or also the EntitySet in the EntityContainer (or both). Currently only the EntityType definition is targeted. EntitySet-level annotations (e.g.Capabilities) sit on the EntitySet, not the EntityType, and are not reachable via the current selector —jsonPathis the current fallback for those cases. - Consider aligning OData selectors with the standard OData CSDL Annotation Target syntax. OData defines a well-specified path grammar for identifying any CSDL element as an annotation target (e.g.
MyService.MyEntityType/MyProperty,MyService.MyEntityContainer/MyEntitySet). Using this as the native OData selector format would piggyback on an existing standard and avoid inventing a parallel addressing scheme. The trade-off is that consumers and implementors need deeper OData knowledge to construct and interpret selectors correctly, compared to the current named-key approach. Reference: OData CSDL XML 4.01. - Not sure if we need fully qualified selectors, maybe we can support both and only require fully qualified selectors in cases where it's ambiguous.
Selectors in General:
Use @EntityRelationship annotations if available as selector for EntityType or PropertyType?