3.3.3. SOVD-API

3.3.3.1. Data Types

Software Architecture: ODX to JSON data type mapping arch~sovd-api-data-types-mapping-iso17978
status: draft

Data types must be mapped as follows:

ODX to JSON data type mapping

ODX data type

JSON data type (format)

Comment

A_ASCIISTRING

string

A_BOOLEAN

boolean

A_BYTEFIELD

string (byte | hex)

see Data Type A_BYTEFIELD as Hex

A_FLOAT32

number (float)

A_FLOAT64

number (double)

A_INT32

integer (int32)

A_UINT32

integer (int64)

A_UNICODE2STRING

string

A_UTF8STRING

string

Primitive JSON types

All primitive JSON types (string, array, number, integer, boolean, and object) can be used.

For strings, the following format identifiers can be used:

JSON string formats

JSON type

JSON format

Comment

string

byte

Base64-encoded binary data

string

hex

Hexadecimal-encoded binary data (e.g. f0cacc1a). Can be prefixed with 0x and contain spaces.

string

uuid

UUID identifier according to RFC 4122 (https://www.rfc-editor.org/rfc/rfc4122)

string

uri

Absolute URI according to RFC 3986 (https://www.rfc-editor.org/rfc/rfc3986)

string

uri-reference

Relative URI according to RFC 3986 (https://www.rfc-editor.org/rfc/rfc3986)

string

json-pointer

Pointer to a specific value within the JSON according to RFC 6901 (https://www.rfc-editor.org/rfc/rfc6901)

Note

TODO More string formats required?

Mapping of complex data types

Note

TODO Mapping of complex data types

3.3.3.2. Bulk Data

Software Architecture: Bulk-Data Endpoints arch~sovd-api-bulk-data
status: draft

Bulk-data endpoints allow the management of bulk data, like files that are to be used for flashing.

Paths are required to be in the following structure: /bulk-data/{category}/{id}. For extensions, the name bulk-data may only be used at the end of a path element.

Bulk Data endpoints

Method

Path

Description

GET

/bulk-data/{category}

Retrieves a list of entries in that category and their IDs

GET

/bulk-data/{category}/{entry-id}

Downloads the data for the entry. The MIME type is determined by the server and the content of the data.

POST

/bulk-data/{category}

Uploads data to the category. Additional metadata (e.g. filename) can be provided through Content-Disposition: form-data

DELETE

/bulk-data/{category}

Requests the deletion of all data for that category

DELETE

/bulk-data/{category}/{entry-id}

Requests the deletion of a specific entry

Note

IMPORTANT: All calls to the aforementioned endpoints can fail with reasonable HTTP status codes (e.g. 401, 403, 409, 501), depending on the context and state.

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Bulk-Data Endpoints

participant Client
participant "HTTP Server\n(Axum)" as HTTP
participant "Security\nMiddleware" as SEC
participant "Bulk-Data\nHandler" as HANDLER
participant "File System /\nStorage" as FS

== List entries ==

Client -> HTTP : GET /bulk-data/{category}
activate HTTP
HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC
HTTP -> HANDLER : route to bulk-data handler
activate HANDLER
HANDLER -> FS : list entries in category
activate FS
FS -> HANDLER : entries with IDs and metadata
deactivate FS
HANDLER -> HTTP : JSON body
deactivate HANDLER
HTTP -> Client : HTTP 200 OK\n{ "items": [ { "id": "...", ... }, ... ] }
deactivate HTTP

== Download entry ==

Client -> HTTP : GET /bulk-data/{category}/{entry-id}
activate HTTP
HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC
HTTP -> HANDLER : route to bulk-data handler
activate HANDLER
HANDLER -> FS : read entry data
activate FS
FS -> HANDLER : binary data
deactivate FS
HANDLER -> HTTP : binary response\n(MIME type determined by content)
deactivate HANDLER
HTTP -> Client : HTTP 200 OK\nContent-Type: <mime-type>\n<binary data>
deactivate HTTP

== Upload entry ==

Client -> HTTP : POST /bulk-data/{category}\nContent-Disposition: form-data\n<binary data>
activate HTTP
HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC
HTTP -> HANDLER : route to bulk-data handler
activate HANDLER
HANDLER -> FS : store data with metadata
activate FS
FS -> HANDLER : stored (entry-id)
deactivate FS
HANDLER -> HTTP : JSON body
deactivate HANDLER
HTTP -> Client : HTTP 201 Created\n{ "id": "<entry-id>" }
deactivate HTTP

== Delete entry ==

Client -> HTTP : DELETE /bulk-data/{category}/{entry-id}
activate HTTP
HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC
HTTP -> HANDLER : route to bulk-data handler
activate HANDLER
HANDLER -> FS : delete entry
activate FS
FS -> HANDLER : deleted
deactivate FS
HANDLER -> HTTP : success
deactivate HANDLER
HTTP -> Client : HTTP 204 No Content
deactivate HTTP

@enduml

3.3.3.3. Entities

Software Architecture: Components Entity Collection arch~sovd-api-components-entity-collection
status: draft

The /components endpoint serves as the entry point for discovering available ECU entities.

GET /components

Returns a list of all ECU entities that have been loaded from diagnostic descriptions (MDD files). Each item in the list contains the ECU name, a lowercase identifier, and a URI reference to the individual component resource.

The response may include additional fields beyond the standard items list. These additional fields group ECUs based on configurable conditions evaluated against the diagnostic description metadata. The names and filter criteria for these additional fields are defined in the application configuration.

GET /components/{ecu-name}

Returns detailed information about a specific ECU entity, including:

  • The ECU identifier and name

  • Variant information (name, base variant flag, connectivity state, and logical address)

  • A last_seen timestamp of the last successful diagnostic contact with the ECU (see ECU States (arch~dt-ecu-states)), if the ECU has ever been contacted (either in the current session, or, when loaded from a persisted ECU list, in a previous session)

  • URI references to the standardized resource collection endpoints: data, operations, configurations, faults, modes, locks, and extension endpoints

The connectivity state of an ECU reflects its current diagnostic reachability and variant detection status:

ECU connectivity states

State

Description

Online

The ECU is reachable and has a detected variant. This also covers the internal AssumedOnline state (see ECU States (arch~dt-ecu-states)), i.e. an ECU known to have been Online in a previous session (from a persisted ECU list) but not yet contacted in the current session; the last_seen timestamp allows clients to tell these two cases apart.

Offline

The ECU has not been contacted since startup

NotTested

Variant detection has not yet been performed

Duplicate

Multiple variants match the ECU response, superseded by a more specific match

Disconnected

The ECU was previously reachable but is no longer responding

NoVariantDetected

The ECU responded but no matching variant was found

Optionally, diagnostic description metadata (SDGs) for the ECU can be included in the response through a query parameter.

Software Architecture: Standardized Resource Collection Mapping arch~sovd-api-standardized-resource-collection-mapping

Every ECU with a mdd file is an entity within the /components entity collection.

This doesn’t include the mdd files used for functional communication (see Functional communication).

3.3.3.4. ECU resource collection

Software Architecture: ECU Resource Collection arch~sovd-api-ecu-resource-collection
status: draft

Each ECU entity must provide a standardized resource collection as defined in ISO 17978-3, chapter 5.4.2.

The resource collection for ECUs is defined in an OpenAPI Specification: ECU Resource Collection Specification

3.3.3.5. SDG/SD Metadata

Software Architecture: Component SDG/SDs arch~sovd-api-component-sdgsd

Special Data Groups (SDGs) and Special Data (SDs) from the diagnostic description can be retrieved through an opt-in query parameter x-sovd2uds-includesdgs (with alias x-include-sdgs). When set to true, the response includes the SDG/SD metadata instead of or in addition to the normal response data.

ECU-level SDGs

On the GET /components/{ecu-name} endpoint, including SDGs adds an sdgs property to the ECU response object. The SDGs returned are those associated with the ECU entity in the diagnostic description (retrieved without a specific service context).

Service-level SDGs

On the GET /components/{ecu-name}/data/{data-identifier} endpoint, when SDGs are requested, the endpoint returns the SDGs associated with the diagnostic service instead of the normal data response. The response contains an items map keyed by a combination of the service name and its action type, where each entry holds the list of SDGs for that service action.

Operation-level SDGs

On the GET /components/{ecu-name}/operations/{operation-identifier} endpoint, when SDGs are requested, the endpoint returns the SDGs associated with the diagnostic service instead of the normal data response. The response contains an items map keyed by a combination of the service name and its action type, where each entry holds the list of SDGs for that service action.

For asynchronous operations (which consist of multiple subfunctions such as Start, Stop, RequestResults), each subfunction’s SDGs are returned as separate entries in the items map, keyed by {service_name}_{action_type} (lowercased). This naturally separates potentially conflicting SDGs from different subfunctions without requiring wrapper entries.

Data format

The SDG/SD structure is recursive. Each entry in the list is one of two types:

SD entry fields

Field

Type

Description

value

string (optional)

The value of the SD

si

string (optional)

Semantic information – a descriptor or key for the entry

ti

string (optional)

Text information – the textual content of the entry

SDG entry fields

Field

Type

Description

caption

string (optional)

The name of the group

si

string (optional)

Semantic information – a descriptor or key for the group

sdgs

list (optional)

A nested list of SD and SDG entries, allowing arbitrary nesting depth

SD and SDG entries are distinguished by their structure – an entry with a sdgs or caption field is an SDG, while an entry with value or ti fields is an SD.

3.3.3.6. Data Resources – SID 2216 & 2E16

Software Architecture: Data Resources arch~sovd-api-data-resources
status: draft

Data resources for ECUs are available in the standardized resource collection within the path /components/{ecu-name}/data.

The data main path returns a list of the data identifiers available as /data/{data-identifier}, as well as metadata.

A data identifier in the list is described with the following attributes (all strings):

Data identifier attributes

Attribute

Description

id

Path element ID (i.e. short name)

name

Name of the element (i.e. long name)

category

Category of the element

Naming

Names for data resources are determined by taking all diag-services defined for 2216 and 2E16 – their short name is taken as a base and processed by removing configurable prefixes/suffixes, to determine the data identifier within the /data/{data-identifier} path.

The following diagrams illustrate the message flow for reading and writing data resources:

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Data Read -- SID 22

participant Client
participant "HTTP Server\n(Axum)" as HTTP
participant "Security\nMiddleware" as SEC
participant "Data Handler" as HANDLER
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

Client -> HTTP : GET /components/{ecu}/data/{id}
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to data handler
activate HANDLER

HANDLER -> DIAG : read data (service name, variant)
activate DIAG

DIAG -> DIAG : resolve service from MDD\n(short name -> SID 22 + DID)
DIAG -> DIAG : build UDS request payload\n(22 {DID})

DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : DoIP -> UDS ReadDataByIdentifier\n(22 {DID})
activate ECU
ECU -> COMM : positive response\n(62 {DID} {data})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> DIAG : decode UDS response\ninto named parameters\n(using MDD codec definitions)
DIAG -> HANDLER : decoded parameters
deactivate DIAG

HANDLER -> HANDLER : map parameters to\nSOVD JSON response
HANDLER -> HTTP : JSON body
deactivate HANDLER

HTTP -> Client : HTTP 200 OK\n{ "id": "...", "data": { ... } }
deactivate HTTP

@enduml

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Data Write -- SID 2E

participant Client
participant "HTTP Server\n(Axum)" as HTTP
participant "Security\nMiddleware" as SEC
participant "Data Handler" as HANDLER
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

Client -> HTTP : PUT /components/{ecu}/data/{id}\n{ "data": { ... } }
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to data handler
activate HANDLER

HANDLER -> HANDLER : extract named parameters\nfrom JSON request body

HANDLER -> DIAG : write data (service name, parameters)
activate DIAG

DIAG -> DIAG : resolve service from MDD\n(short name -> SID 2E + DID)
DIAG -> DIAG : encode named parameters\ninto UDS request payload\n(2E {DID} {encoded data})

DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : DoIP -> UDS WriteDataByIdentifier\n(2E {DID} {data})
activate ECU
ECU -> COMM : positive response\n(6E {DID})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> HANDLER : write confirmed
deactivate DIAG

HANDLER -> HTTP : success
deactivate HANDLER

HTTP -> Client : HTTP 200 OK
deactivate HTTP

@enduml

3.3.3.7. Categories

Software Architecture: Data Identifier Categories arch~sovd-api-data-identifier-categories
status: draft

The category of a data identifier must be mappable with configuration, in which the functional class name is mapped to a category name.

The following standard categories are defined by the standard:

Standard categories

Name

Description

identData

Identification data – everything related to the identification of an ECU/vehicle

currentData

Measurement data that can dynamically change

storedData

Parameters stored in the ECU

sysInfo

System information - data related to system resources that can change dynamically (e.g. memory consumption)

Additional custom categories must be prefixed with x-sovd2uds-, or, in custom vendor configuration, with a vendor-specific prefix different from x-sovd2uds.

Services without a mapping should be ignored to allow a separation between configuration and data services.

3.3.3.8. Configurations – SID 2216 & 2E16

Software Architecture: Configuration Resources arch~sovd-api-configuration-resources
status: draft

Names for data resources are determined by taking all diag-services defined for 2216 and 2E16, and filtering them for a configurable functional class name. Their short name is taken as a base and processed by removing configurable prefixes/suffixes, to determine the data identifier within the /configurations/{data-identifier} path.

The returned item properties for the /configurations item list are:

Configuration item properties

Attribute

Description

id

Path element ID (i.e. short name)

name

Name of the element (i.e. long name)

type

Always parameter

x-sovd2uds-serviceAbstract

Array of strings containing the SIDs and data identifier as a hexadecimal string (e.g. [“2E1234”, “221234”])

The following diagrams illustrate the message flow for reading and writing configuration resources:

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Configuration Read -- SID 22

participant Client
participant "HTTP Server\n(Axum)" as HTTP
participant "Security\nMiddleware" as SEC
participant "Configuration\nHandler" as HANDLER
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

Client -> HTTP : GET /components/{ecu}/configurations/{id}
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to configuration handler
activate HANDLER

HANDLER -> DIAG : read configuration (service name, variant)
activate DIAG

DIAG -> DIAG : resolve service from MDD\n(short name -> SID 22 + DID)
DIAG -> DIAG : build UDS request payload\n(22 {DID})

DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : DoIP -> UDS ReadDataByIdentifier\n(22 {DID})
activate ECU
ECU -> COMM : positive response\n(62 {DID} {data})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> DIAG : decode UDS response\ninto named parameters\n(using MDD codec definitions)
DIAG -> HANDLER : decoded parameters
deactivate DIAG

HANDLER -> HANDLER : map parameters to\nSOVD JSON response
HANDLER -> HTTP : JSON body
deactivate HANDLER

HTTP -> Client : HTTP 200 OK\n{ "id": "...", "data": { ... } }
deactivate HTTP

@enduml

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Configuration Write -- SID 2E

participant Client
participant "HTTP Server\n(Axum)" as HTTP
participant "Security\nMiddleware" as SEC
participant "Configuration\nHandler" as HANDLER
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

Client -> HTTP : PUT /components/{ecu}/configurations/{id}\n{ "data": { ... } }
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to configuration handler
activate HANDLER

HANDLER -> HANDLER : extract named parameters\nfrom JSON request body

HANDLER -> DIAG : write configuration (service name, parameters)
activate DIAG

DIAG -> DIAG : resolve service from MDD\n(short name -> SID 2E + DID)
DIAG -> DIAG : encode named parameters\ninto UDS request payload\n(2E {DID} {encoded data})

DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : DoIP -> UDS WriteDataByIdentifier\n(2E {DID} {data})
activate ECU
ECU -> COMM : positive response\n(6E {DID})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> HANDLER : write confirmed
deactivate DIAG

HANDLER -> HTTP : success
deactivate HANDLER

HTTP -> Client : HTTP 200 OK
deactivate HTTP

@enduml

Note

x-sovd2uds-serviceAbstract is an extension to the standard.

Rationale for serviceAbstract

Coding data files might not include the matching name for a service, or detailed JSON parameters that would be required to code an ECU. Therefore, a “reverse lookup” to the name can be required, so a client without access to the diagnostic description is able to code an ECU just with the 2E 1234 <payload> data, utilizing the application/octet-stream extension for a PUT /configurations/{data-identifier} call.

3.3.4. Operations

Software Architecture: Synchronous and Asynchronous Operations arch~sovd-api-operations-handling
status: draft

Operations in the CDA are Routines (3116), Reset (1116), and an extension to configure communication parameters (Communication Parameters (ComParams)).

Reset – SID 1116

For compatibility with SOVD version 1.0 and earlier, the operations /operations/ecureset and /operations/reset to reset an ECU must be supported.

Routines – SID 3116

All services with the SID 3116 are considered for operations – as with data, their short names are preprocessed by removing configurable prefixes/suffixes to determine routine identifiers available as the /operations/{routine-identifier} path.

The items in the list of items available under /operations must include the following attributes:

Operation list item attributes

Attribute

Type

Description

id

string

Path element for the routine identifier (i.e. short name)

name

string

Name of the routine (long name)

proximity_proof_required

boolean

Always false

asynchronous_execution

boolean

Either true or false, depending on the defined subfunctions for the routine

Synchronous – Start only

When a routine only defines the Start (0x01) subfunction, it is considered synchronous. This means that the return for asynchronous_execution in the list will be false, and that a call to execute the routine with POST /operations/{routine-name}/executions is executed synchronously and will directly return the response from the ECU with HTTP status 200 OK.

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Synchronous Operation -- SID 31 (Start only)

participant Client
participant "HTTP Server\n(Axum)" as HTTP
participant "Security\nMiddleware" as SEC
participant "Operations\nHandler" as HANDLER
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

Client -> HTTP : POST /components/{ecu}/operations/{routine}/executions\n{ "parameters": { ... } }
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to operations handler
activate HANDLER

HANDLER -> DIAG : execute routine (Start subfunction)
activate DIAG

DIAG -> DIAG : resolve routine from MDD\n(short name -> SID 31 + routine ID)
DIAG -> DIAG : encode parameters into UDS payload\n(31 01 {routine ID} {params})

DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : DoIP -> UDS RoutineControl Start\n(31 01 {routine ID} {params})
activate ECU
ECU -> ECU : execute routine
ECU -> COMM : positive response\n(71 01 {routine ID} {result})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> DIAG : decode response parameters
DIAG -> HANDLER : decoded result
deactivate DIAG

HANDLER -> HANDLER : build SOVD JSON response

HANDLER -> HTTP : JSON body
deactivate HANDLER

HTTP -> Client : HTTP 200 OK\n{ "data": { ... } }
deactivate HTTP

@enduml

Note

Operations without a Start subfunction can exist in the operations list but will fail execution with an error unless the x-sovd2uds-suppressService query parameter is set to true.

Asynchronous – Stop and/or RequestResults

When a routine has Stop (0x02) and/or RequestResults (0x03) subfunctions defined, it is considered asynchronous. This means that the return for asynchronous_execution in the list will be true, and that a call to execute the routine with POST /operations/{routine-name}/executions is executed on the ECU and will return the response from the ECU, as well as an id and the other asynchronous properties required by the standard for calling the RequestResults subfunction with GET /operations/{routine-name}/executions/{id}.

The POST request returns HTTP status 202 ACCEPTED with an execution identifier.

Additionally, by calling DELETE /operations/{routine-name}/executions/{id}, it’s possible to call the Stop subfunction of the routine.

Subfunction Requirements

If any of the required subfunctions are not available in the diagnostic database, the call will result in an error:

  • POST requires the Start (0x01) subfunction to be defined

  • GET requires the RequestResults (0x03) subfunction to be defined

  • DELETE requires the Stop (0x02) subfunction to be defined

These requirements can be bypassed using the x-sovd2uds-suppressService query parameter. Since an entry in the list is still required, as well as the operation being asynchronous, the definition of either RequestResults or Stop is a prerequisite.

Force Parameter

If DELETE is called and an ECU error is encountered, the id will not be deleted unless the query parameter x-sovd2uds-force is set to true. This allows the client to handle returned errors and to call the Stop subfunction again.

When x-sovd2uds-force=true, the execution is removed from tracking even if the Stop request fails or returns a negative response.

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Asynchronous Operation -- SID 31 (Start + RequestResults + Stop)

participant Client
participant CDA
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

!pragma teoz true

== Start Routine ==

Client -> CDA : POST /components/{ecu}/operations/{routine}/executions\n{ "parameters": { ... } }
activate CDA

CDA -> DIAG : execute routine (Start)
activate DIAG
DIAG -> DIAG : encode parameters\n(31 01 {routine ID} {params})
DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : RoutineControl Start\n(31 01 {routine ID} {params})
activate ECU
ECU -> COMM : positive response\n(71 01 {routine ID} {result})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM
DIAG -> CDA : decoded result
deactivate DIAG

CDA -> CDA : generate execution {id}\ntrack execution state
CDA -> Client : HTTP 202 Accepted\n{ "id": "{id}", "status": "running",\n  "data": { ... } }
deactivate CDA

== Poll Results ==

Client -> CDA : GET /components/{ecu}/operations/{routine}/executions/{id}
activate CDA

CDA -> DIAG : request results (RequestResults)
activate DIAG
DIAG -> DIAG : encode request\n(31 03 {routine ID})
DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : RoutineControl RequestResults\n(31 03 {routine ID})
activate ECU
ECU -> COMM : positive response\n(71 03 {routine ID} {result})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM
DIAG -> CDA : decoded result
deactivate DIAG

CDA -> Client : HTTP 200 OK\n{ "id": "{id}", "status": "completed",\n  "data": { ... } }
deactivate CDA

== Stop Routine (optional) ==

Client -> CDA : DELETE /components/{ecu}/operations/{routine}/executions/{id}
activate CDA

CDA -> DIAG : stop routine (Stop)
activate DIAG
DIAG -> DIAG : encode request\n(31 02 {routine ID})
DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : RoutineControl Stop\n(31 02 {routine ID})
activate ECU
ECU -> COMM : positive response\n(71 02 {routine ID})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM
DIAG -> CDA : confirmed
deactivate DIAG

CDA -> CDA : remove execution {id}\nfrom tracking
CDA -> Client : HTTP 204 No Content
deactivate CDA

@enduml

Stop Response Data

When a Stop subfunction returns non-empty response data, the DELETE endpoint returns HTTP status 200 OK with the response data in the body, instead of the standard 204 NO CONTENT. This allows clients to access any data returned by the Stop operation.

Note

This is an extension to the standard to support Stop operations that return response data.

Rationale for POST Response Data

When executing an asynchronous function, there’s no good way to return the response of the routine with the GET to the id-endpoint, since that endpoint should only return the status of the RequestResults call. Therefore, the response of the routine is returned directly when executing the routine with POST in addition to the id.

Note

This is a deviation from the standard, but is required to allow clients to handle routine responses properly.

3.3.4.1. IOControl – SID 2A16

Note

Not supported at this time

3.3.5. Modes

3.3.5.1. Session – SID 1016

Software Architecture: Session Endpoints arch~sovd-api-session-management
status: draft

The endpoint /modes/session can be used to determine the current ECU session, as well as trying to switch into a different session.

Session endpoints

Method

Path

Description

GET

/modes/session

Returns the current session

PUT

/modes/session

Tries to switch into the specified session

The format for the request body is:

{
  "value": "<session name>",
  "mode_expiration": 3600
}

The names of the sessions for the field value are determined by the short name for the state in the ECU’s state chart for the SID 1016 services. It is case-insensitive.

The field mode_expiration is optional. If set, it determines the time in seconds that the session should be active. Once that time expires, the session is automatically reset to the default session.

In the response body, id and value must be included.

See also chapter 7.16 in ISO 17978-3.

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Session Switch -- SID 10

participant Client
participant CDA
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

== Read Current Session ==

Client -> CDA : GET /components/{ecu}/modes/session
activate CDA
CDA -> Client : HTTP 200 OK\n{ "id": "...", "value": "defaultSession" }
deactivate CDA

== Switch Session ==

Client -> CDA : PUT /components/{ecu}/modes/session\n{ "value": "extendedDiagnosticSession",\n  "mode_expiration": 3600 }
activate CDA

CDA -> DIAG : switch session (session name)
activate DIAG

DIAG -> DIAG : resolve session name\nvia MDD state chart\n(name -> SID 10 + subfunction)

DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : DoIP -> UDS DiagnosticSessionControl\n(10 {subfunction})
activate ECU
ECU -> COMM : positive response\n(50 {subfunction} {timing params})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> CDA : session switched
deactivate DIAG

CDA -> CDA : start mode expiration\ntimer if configured

CDA -> Client : HTTP 200 OK\n{ "id": "...", "value": "extendedDiagnosticSession" }
deactivate CDA

@enduml

3.3.5.2. Security – SID 2716

Software Architecture: Security Access Endpoints arch~sovd-api-security-access-modes
status: draft

The endpoints are available under the path /modes/security.

Works similarly to Session defined in the previous chapter. The names of the security access levels are determined through the state charts for the SID 2716 services.

RequestSeed flow

A client initiates security access by sending a PUT /modes/security request with a value field that encodes both the target level and whether this is a RequestSeed or SendKey request. The CDA inspects the value to determine:

  • level – the state-chart level name, obtained by stripping the trailing _RequestSeed suffix when present (e.g. Level_7_RequestSeed -> Level_7, Supplier_RequestSeed -> Supplier)

  • whether the request is a RequestSeed (value ends with _RequestSeed) or a SendKey (value is the level name alone, accompanied by a key)

Example values and their parsed components:

value field

level

Request type

Level_7_RequestSeed

Level_7

RequestSeed

Supplier_RequestSeed

Supplier

RequestSeed

Supplier

Supplier

SendKey

RequestSeed service name resolution

The CDA resolves the UDS RequestSeed service (SID 2716) by searching all SID 2716 services in the ISO 14229-1 RequestSeed subfunction range (odd subfunctions 1, 3-5, 7-41, exactly 2 request parameters) and selecting the first whose short name contains the level name (underscores stripped, case-insensitive).

This requires the level name to be embedded in the service short name, which both supported naming conventions satisfy:

  • Level-encoded names (e.g. RequestSeed_Level_3): the level substring Level3 is contained in the short name.

  • Semantic label names (e.g. RequestSeed_Supplier): the label Supplier is both the level name and the label in the short name.

Naming convention examples

Short name in description

Subfunction

Level value

Resolved by

RequestSeed_Level_3

0x03

Level_3

level substring Level3 found in short name

RequestSeed_Level_7

0x07

Level_7

level substring Level7 found in short name

RequestSeed_Supplier

0x09

Supplier

level substring Supplier found in short name

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Security Access -- SID 27

participant Client
participant "HTTP Server\n(Axum)" as HTTP
participant "Security\nMiddleware" as SEC
participant "Modes Handler" as HANDLER
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

== GET current security level ==

Client -> HTTP : GET /components/{ecu}/modes/security
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to modes handler
activate HANDLER

HANDLER -> DIAG : get current security state
activate DIAG
DIAG -> HANDLER : current security level name
deactivate DIAG

HANDLER -> HTTP : JSON body
deactivate HANDLER

HTTP -> Client : HTTP 200 OK\n{ "name": "Security access", "value": "<level>" }
deactivate HTTP

== PUT requestSeed (no Key field) ==

Client -> HTTP : PUT /components/{ecu}/modes/security\n{ "value": "<level>_RequestSeed" }
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to modes handler
activate HANDLER

HANDLER -> DIAG : request seed (level name)
activate DIAG

DIAG -> DIAG : resolve state chart\n(level name -> SID 27 subfunction)

DIAG -> COMM : send UDS request (requestSeed)
activate COMM
COMM -> ECU : DoIP -> UDS SecurityAccess\n(27 {subfunction})
activate ECU
ECU -> COMM : positive response\n(67 {subfunction} {seed})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> HANDLER : seed value
deactivate DIAG

HANDLER -> HTTP : JSON body
deactivate HANDLER

HTTP -> Client : HTTP 200 OK\n{ "id": "security",\n"seed": { "Request_Seed": "0xAB 0xCD 0xEF ..." } }
deactivate HTTP

== PUT sendKey (Key field present) ==

Client -> HTTP : PUT /components/{ecu}/modes/security\n{ "value": "<level>",\n"Key": { "Send_Key": "0xAB 0xCD ..." } }
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to modes handler
activate HANDLER

HANDLER -> DIAG : send key (level name, key)
activate DIAG

DIAG -> DIAG : resolve state chart\n(level name -> SID 27 subfunction+1)

DIAG -> COMM : send UDS request (sendKey)
activate COMM
COMM -> ECU : DoIP -> UDS SecurityAccess\n(27 {subfunction+1} {key})
activate ECU
ECU -> COMM : positive response\n(67 {subfunction+1})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> HANDLER : security access granted
deactivate DIAG

HANDLER -> HTTP : JSON body
deactivate HANDLER

HTTP -> Client : HTTP 200 OK\n{ "id": "security", "value": "<level>" }
deactivate HTTP

@enduml

3.3.5.3. Authentication – SID 2916

Software Architecture: Authentication Endpoints arch~sovd-api-authentication-modes
status: draft

Note

This is technically a deviation from Table 343 in the ISO API. The table in the ISO is misleading, since 8.3.2 and 8.3.3 describe them separately.

The endpoints are available under /modes/authentication. A PUT call needs to provide a request body containing value with the desired subfunction (names are determined by the UDS standard), and a parameters field containing all request parameters.

Diagnostic data descriptions have to specify the used services including the subfunction individually, so the request parameters can be converted into UDS payloads.

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Authentication -- SID 29

participant Client
participant "HTTP Server\n(Axum)" as HTTP
participant "Security\nMiddleware" as SEC
participant "Modes Handler" as HANDLER
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

Client -> HTTP : PUT /components/{ecu}/modes/authentication\n{ "value": "<subfunction>", "parameters": { ... } }
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to modes handler
activate HANDLER

HANDLER -> DIAG : authentication request (subfunction, parameters)
activate DIAG

DIAG -> DIAG : resolve service from MDD\n(subfunction name -> SID 29 + subfunction byte)
DIAG -> DIAG : encode parameters into\nUDS request payload

DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : DoIP -> UDS Authentication\n(29 {subfunction} {params})
activate ECU
ECU -> COMM : positive response\n(69 {subfunction} {response data})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> DIAG : decode UDS response\ninto named parameters
DIAG -> HANDLER : decoded parameters
deactivate DIAG

HANDLER -> HANDLER : map parameters to\nSOVD JSON response
HANDLER -> HTTP : JSON body
deactivate HANDLER

HTTP -> Client : HTTP 200 OK\n{ "id": "authentication", "value": "<subfunction>",\n"parameters": { ... } }
deactivate HTTP

@enduml

3.3.5.4. Communication Control – SID 2816

Software Architecture: Communication Control Endpoints arch~sovd-api-communication-control-modes
status: draft

To control the communication parameters of an ECU, the path /modes/commctrl is offered, which can be called similarly to Session (without expiration).

The attribute value allows the following subfunction names based on the UDS standard:

  • enableRxAndEnableTx

  • enableRxAndDisableTx

  • disableRxAndEnableTx

  • disableRxAndDisableTx

Matching 2816 service entries must be present in the diagnostic description. Parameters can be provided through an additional parameters attribute.

Note

Other values are not supported.

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Communication Control -- SID 28

participant Client
participant "HTTP Server\n(Axum)" as HTTP
participant "Security\nMiddleware" as SEC
participant "Modes Handler" as HANDLER
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

Client -> HTTP : PUT /components/{ecu}/modes/commctrl\n{ "value": "<subfunction>", "parameters": { ... } }
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to modes handler
activate HANDLER

HANDLER -> DIAG : set communication control (subfunction, parameters)
activate DIAG

DIAG -> DIAG : resolve service from MDD\n(subfunction name -> SID 28 + subfunction byte)
DIAG -> DIAG : encode parameters into\nUDS request payload

DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : DoIP -> UDS CommunicationControl\n(28 {subfunction} {params})
activate ECU
ECU -> COMM : positive response\n(68 {subfunction})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> HANDLER : communication control confirmed
deactivate DIAG

HANDLER -> HTTP : JSON body
deactivate HANDLER

HTTP -> Client : HTTP 200 OK\n{ "id": "commctrl", "value": "<subfunction>" }
deactivate HTTP

@enduml

3.3.5.5. DTC Setting – SID 8516

Software Architecture: DTC Setting Endpoints arch~sovd-api-dtc-setting-modes
status: draft

To control the DTC settings of an ECU, the path /modes/dtcsetting is offered, which can be called similarly to Session (without expiration).

The attribute value allows the values off and on, to call the corresponding subfunctions on the ECU.

Matching 8516 service entries must be present in the diagnostic description. Parameters can be provided through an additional parameters attribute.

Note

Other specific extensions to the values are not supported.

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title DTC Setting -- SID 85

participant Client
participant "HTTP Server\n(Axum)" as HTTP
participant "Security\nMiddleware" as SEC
participant "Modes Handler" as HANDLER
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

Client -> HTTP : PUT /components/{ecu}/modes/dtcsetting\n{ "value": "off", "parameters": { ... } }
activate HTTP

HTTP -> SEC : authenticate & authorize
activate SEC
SEC -> HTTP : OK
deactivate SEC

HTTP -> HANDLER : route to modes handler
activate HANDLER

HANDLER -> DIAG : set DTC setting (value, parameters)
activate DIAG

DIAG -> DIAG : resolve service from MDD\n(value -> SID 85 subfunction)
DIAG -> DIAG : encode parameters into\nUDS request payload

DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : DoIP -> UDS ControlDTCSetting\n(85 {subfunction} {params})
activate ECU
ECU -> COMM : positive response\n(C5 {subfunction})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> HANDLER : DTC setting confirmed
deactivate DIAG

HANDLER -> HTTP : JSON body
deactivate HANDLER

HTTP -> Client : HTTP 200 OK\n{ "id": "dtcsetting", "value": "off" }
deactivate HTTP

@enduml

3.3.6. Faults – SID 1416 & 1916

Software Architecture: Faults endpoint arch~sovd-api-faults-endpoint
status: draft

The following operations must be implemented:

Faults endpoints

Method

Path

Description

GET

/faults

Retrieves a list of DTCs stored in the ECU:

  • To filter the DTCs, the query parameter status can be used.

GET

/faults/<dtc>

Retrieves detailed information about the DTC:

  • Can include snapshot and extended data within the environment_data object, when the query parameter include-extended-data or include-snapshot are set to true.

DELETE

/faults

Clears all DTCs stored in the ECU

DELETE

/faults/<dtc>

Clears the provided DTC from the ECU

The query parameter status[<key>]=<value> can be used to query/filter the returned DTCs based on their status. It can be used multiple times to combine different status flags. The values correspond to the DTC status bits defined in ISO 14229-1.

Available keys:

  • confirmedDtc

  • pendingDtc

  • testFailed

  • testFailedSinceLastClear

  • testFailedThisOperationCycle

  • testNotCompletedSinceLastClear

  • testNotCompletedThisOperationCycle

  • warningIndicatorRequested

All values are either boolean values (true/false), or a bit value (0/1).

Additionally, a special key called mask is available, which takes a hexadecimal mask as a value to allow filtering by the complete status byte. Using other keys together with mask is not supported.

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Fault Read -- SID 19

participant Client
participant CDA
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

== List All Faults ==

Client -> CDA : GET /components/{ecu}/faults\n?status[confirmedDtc]=true
activate CDA

CDA -> DIAG : read DTCs (status mask)
activate DIAG

DIAG -> DIAG : build status mask byte\nfrom query parameters

DIAG -> COMM : send UDS request
activate COMM
COMM -> ECU : DoIP -> UDS ReadDTCInformation\n(19 02 {status mask})
activate ECU
ECU -> COMM : positive response\n(59 02 {availability mask} {DTC records})
deactivate ECU
COMM -> DIAG : raw UDS response
deactivate COMM

DIAG -> DIAG : parse DTC records\n(DTC number + status byte)
DIAG -> CDA : list of DTCs with status
deactivate DIAG

CDA -> CDA : map DTCs to SOVD\nfault representation

CDA -> Client : HTTP 200 OK\n{ "items": [ { "id": "...", "status": { ... } }, ... ] }
deactivate CDA

== Read Single Fault with Extended Data ==

Client -> CDA : GET /components/{ecu}/faults/{dtc}\n?include-extended-data=true&include-snapshot=true
activate CDA

CDA -> DIAG : read DTC detail + extended + snapshot
activate DIAG

DIAG -> COMM : send UDS request(s)
activate COMM
COMM -> ECU : ReadDTCInformation\n(19 04/06 {DTC} ...)
activate ECU
ECU -> COMM : positive response(s)\nwith snapshot & extended data
deactivate ECU
COMM -> DIAG : raw UDS response(s)
deactivate COMM

DIAG -> DIAG : decode snapshot &\nextended data records
DIAG -> CDA : DTC detail with environment data
deactivate DIAG

CDA -> Client : HTTP 200 OK\n{ "id": "...", "status": { ... },\n  "environment_data": { ... } }
deactivate CDA

@enduml

3.3.7. Locks

Software Architecture: Lock API arch~sovd-api-lock-api
status: draft
links incoming: req~sovd-api-lock-api

All three lock scopes share the same CRUD API shape. The scope paths are:

  • Vehicle: /locks

  • ECU: /components/{ecu-name}/locks

  • Functional group: /functions/functionalgroups/{group-name}/locks

Request fields (POST / PUT)

Field

Type

Description

lock_expiration

unsigned integer

Duration in seconds from the current time. The absolute expiration instant is computed at request time.

break_lock

boolean (optional, default false)

Whether an existing lock shall be broken/preempted. See Lock Priority Mechanism Int... (arch~sovd-api-lock-priority).

x_sovd2uds_isexclusive

boolean (optional, default: configurable)

Selects exclusive or non-exclusive enforcement mode. See Lock Exclusivity Policy (arch~sovd-api-lock-exclusivity-policy).

Other properties

any (optional)

Passed verbatim to the priority plugin. Shape is vendor-defined.

Response fields (POST / PUT)

id (UUID string), owned (boolean, always true for the creating client).

Response fields (GET /locks/{id})

lock_expiration (ISO 8601 string). For defunct locks: additionally x_sovd2uds_broken_by (string), x_sovd2uds_broken_at (ISO 8601 string), and x_sovd2uds_current_holder (string, the identity of the current lock holder).

Software Architecture: Lock Exclusivity arch~sovd-api-lock-exclusivity

The x_sovd2uds_isexclusive boolean from the POST/PUT request body is stored as a field on the lock object. If the request body omits the field, the value determined by the configured lock_exclusivity_policy is substituted before storing it (see Lock Exclusivity Policy (arch~sovd-api-lock-exclusivity-policy)). When a request arrives at a communication endpoint the stored flag is read to select the enforcement level applied by ECU Lock Endpoint Enforcement (arch~sovd-api-lock-ecu-enforcement) and Functional Group Lock Endpo... (arch~sovd-api-lock-fg-enforcement).

Software Architecture: Lock Exclusivity Policy arch~sovd-api-lock-exclusivity-policy
status: draft

The configured lock_exclusivity_policy selects the value substituted for x_sovd2uds_isexclusive whenever a lock POST or PUT request body omits that field, before the resulting value is stored on the lock object (see Lock Exclusivity (arch~sovd-api-lock-exclusivity)):

  • exclusive_by_default (default): the substituted value is true.

  • non_exclusive_by_default: the substituted value is false.

The substitution is performed identically for the vehicle, ECU, and functional group lock handlers.

Being enum-typed, this configuration option is designed to accommodate additional exclusivity policies in the future without changing its name or structure.

Requests that explicitly include x_sovd2uds_isexclusive bypass the substitution and use the provided value unchanged.

Software Architecture: Lock Expiration arch~sovd-api-lock-expiration
status: draft

When a lock is created, a background task is spawned that fires at the computed absolute expiration instant. On firing, the task acquires the write lock on the lock map, confirms the stored lock ID still matches (guarding against a race with an extend or a preemption), invokes the lock’s cleanup function, and removes it from the map.

On PUT /locks/{id} (extend), the existing background task is aborted and a new one is spawned for the updated instant.

On explicit DELETE /locks/{id} the background task is aborted before the cleanup function is called, preventing a double-cleanup.

Defunct locks retain their original expiration task, but the task only removes the defunct entry from the defunct store without invoking cleanup.

Software Architecture: ECU Lock Endpoint Enforcement arch~sovd-api-lock-ecu-enforcement

A validate_lock check is applied at the entry of every ECU communication endpoint. The check proceeds as follows:

@startuml
skinparam backgroundColor #FFFFFF
skinparam defaultTextAlignment center

start

:Identify caller from JWT claims;

if (Caller owns a defunct lock\nfor this ECU?) then (yes)
  :HTTP 409 (Conflict);
  stop
endif

if (Active lock held by\nanother client?) then (yes)
  if (Lock is exclusive, or\nwrite operation?) then (yes)
    :HTTP 423 (Locked);
    stop
  else (non-exclusive and read)
    :Proceed;
    stop
  endif
else (no active lock by another)
  if (Caller owns active ECU lock\nor vehicle lock?) then (yes)
    :Proceed;
    stop
  else (no lock held by caller)
    if (Write operation?) then (yes)
      :HTTP 409 (Conflict\n- lock required);
      stop
    else (read)
      :Proceed;
      stop
    endif
  endif
endif

@enduml

ECU Lock Enforcement Decision

The check accepts a vehicle lock owned by the caller as equivalent to owning the ECU lock, granting full write access.

Software Architecture: Functional Group Lock Endpoint Enforcement arch~sovd-api-lock-fg-enforcement

A validate_fg_lock check is applied at the entry of every functional group communication endpoint. It follows the same decision logic as ECU Lock Endpoint Enforcement (arch~sovd-api-lock-ecu-enforcement), operating on the functional group lock and the functional group endpoints (/data, /operations, /modes).

See also Functional Communication EC... (arch~sovd-api-functional-communication-locks) for the Tester Present side-effects associated with acquiring and releasing a functional group lock.

Software Architecture: Lock Requirement Policy arch~sovd-api-lock-requirement-policy

The configured lock_requirement_policy selects a variant of the decision logic used by validate_lock and validate_fg_lock (see ECU Lock Endpoint Enforcement (arch~sovd-api-lock-ecu-enforcement)):

All other branches of the decision logic – defunct lock pre-check, exclusive/ non-exclusive handling while a lock is held by another client, and the vehicle-lock equivalence check – are unaffected by this option.

Being enum-typed, this configuration option is designed to accommodate additional requirement policies in the future without changing its name or structure.

Software Architecture: Lock Acquisition Policy arch~sovd-api-lock-acquisition-policy
status: draft

The ECU lock POST handler and the functional group lock POST handler each evaluate the configured lock_acquisition_policy before creating the child lock, in addition to the existing vehicle-lock ownership check described in Vehicle Lock Blocks Child L... (arch~sovd-api-lock-vehicle-blocking).

Being enum-typed, this configuration option is designed to accommodate additional acquisition policies in the future without changing its name or structure.

Software Architecture: Vehicle Lock Blocks Child Lock Acquisition arch~sovd-api-lock-vehicle-blocking
status: draft

The ECU lock POST handler and the functional group lock POST handler each check for an active vehicle lock before creating the child lock. If a vehicle lock is present and owned by a different client the request is rejected with HTTP 409.

If the vehicle lock is held by the same caller, or if no vehicle lock is held, the child lock creation proceeds normally.

Software Architecture: Lock Priority Mechanism Interface arch~sovd-api-lock-priority
status: draft

When a lock POST request arrives and a lock is already held by a different client, the priority mechanism – if one is registered – is invoked before returning HTTP 409.

Mechanism input

  • JWT claims of the requesting client

  • The identity of the current lock holder, as well as the original properties (TODO: probably better to send all locks to mechanism and let mechanism handle it?)

Mechanism output

  • granted: bool – whether the requesting client has sufficient priority to preempt

  • broken_by: String – the identity string to record in the defunct lock’s x_sovd2uds_broken_by field (typically the requesting client’s JWT sub, but the exact value is determined by the plugin)

If granted is true, the existing lock is transitioned to defunct state (see Defunct Lock Lifecycle (arch~sovd-api-lock-defunct)) and a new lock is created for the requesting client. If no mechanism is registered the handler returns HTTP 409 as normal.

Software Architecture: Defunct Lock Lifecycle arch~sovd-api-lock-defunct

When preemption is granted by the priority mechanism:

  1. The current active lock is marked defunct: a defunct flag is set on the lock object along with broken_by (string returned by the mechanism) and broken_at (current UTC timestamp).

  2. The defunct lock is moved from the active lock slot to a separate per-entity defunct store. The active slot is now free for the new lock.

  3. The defunct lock’s original expiration task is not aborted. When it fires it removes the defunct entry from the defunct store without invoking any cleanup function.

  4. A new lock is created for the preempting client and placed in the active slot with its own expiration task and cleanup function.

GET /locks returns both the active lock and any defunct locks for the entity. Defunct lock entries carry x_sovd2uds_broken_by, x_sovd2uds_broken_at, and x_sovd2uds_current_holder in addition to the standard fields.

Software Architecture: HTTP 409 for Preempted Clients arch~sovd-api-lock-defunct-enforcement

The validate_lock and validate_fg_lock checks are extended with a pre-check that runs before the existing ownership and exclusivity evaluation:

  1. Look up the defunct store for the target entity.

  2. If any defunct lock in that store is owned by the calling client, return HTTP 409 immediately.

This pre-check takes precedence over the HTTP 409 or HTTP 423 that would otherwise be returned for a missing or non-owned active lock.

3.3.8. Generic Service

Software Architecture: Generic Service Endpoint arch~sovd-api-generic-service
status: draft

The /genericservice endpoint provides raw UDS passthrough functionality, allowing clients to send arbitrary UDS requests to an ECU without relying on diagnostic description (MDD) service resolution or parameter encoding.

The client sends a hex-encoded UDS request in the JSON body, and receives the raw hex-encoded UDS response from the ECU.

Permissions for generic service calls can be checked and enforced through the security plugin. Since generic service requests bypass the structured service resolution, the security plugin receives the raw UDS request payload (e.g. 22 F1 90) and is responsible for evaluating whether the authenticated client is authorized to send that specific UDS command to the target ECU.

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Generic Service -- Raw UDS Passthrough

participant Client
participant CDA
participant "Security\nPlugin" as SEC
participant "Diagnostic\nKernel" as DIAG
participant "UDS / DoIP" as COMM
participant ECU

Client -> CDA : PUT /components/{ecu}/genericservice\nContent-Type: application/octet-stream\nAccept: application/octet-stream\nRaw bytes: 22 F1 90
activate CDA

CDA -> DIAG : send raw UDS (byte array)
activate DIAG

DIAG -> DIAG : read SID from first byte (22)\nresolve matching MDD service

note over DIAG : Remaining request bytes are not\nparameter-decoded or validated

DIAG -> DIAG : check service preconditions

DIAG -> SEC : validate resolved diagnostic service
activate SEC
SEC -> SEC : evaluate authorization for service
SEC --> DIAG : authorized
deactivate SEC

DIAG -> COMM : send raw UDS request
activate COMM
COMM -> ECU : DoIP -> raw UDS\n(22 F1 90)
activate ECU
ECU -> COMM : raw UDS response\n(62 F1 90 {data})
deactivate ECU
COMM -> DIAG : raw UDS response bytes
deactivate COMM

DIAG -> CDA : raw response bytes
deactivate DIAG

CDA -> Client : HTTP 200 OK\nContent-Type: application/octet-stream\nRaw bytes: 62 F1 90 {data}
deactivate CDA

@enduml

3.3.9. Version Endpoint

Software Architecture: API Version Endpoint Registration Function arch~sovd-api-version-registration-function

The CDA provides a version registration function that sets up version-related endpoints during initialization.

Registration Function

The function accepts the following parameters: vendor_name, implementation_version, commit, build_date.

It always registers the standard /version-info endpoint, and optionally registers the default /data/version and /apps/sovd2uds/data/version endpoints.

The fields base_uri and api_version are determined by the function.

Standard Endpoint: /version-info

The /version-info endpoint (without version prefix) returns a JSON response per ISO 17978-3 §7.4.1:

{
    "sovd_info": [
        {
            "version": "<sovd_api_version>",
            "base_uri": "<relative uri-reference to base of sovd_api_version>",
            "vendor_info": {
                "name": "<vendor_name>",
                "version": "<implementation_version>",
                "commit": "<commit>",
                "build_date": "<build_date>"
            }
        }
    ]
}

Optional Vendor-Specific Endpoints: /data/version, /apps/sovd2uds/data/version

When enabled, these endpoints are registered as static data endpoints returning:

{
    "id": "version",
    "data": {
        "name": "<vendor_name>",
        "api": {
            "version": "<api_version>"
        },
        "implementation": {
            "version": "<implementation_version>",
            "commit": "<commit>",
            "build_date": "<build_date>"
        }
    }
}

Both endpoint types are available immediately after the HTTP server starts and do not require any ECU communication.

' SPDX-FileCopyrightText: 2026 Copyright (c) Contributors to the Eclipse Foundation
'
' See the NOTICE file(s) distributed with this work for additional
' information regarding copyright ownership.
'
' This program and the accompanying materials are made available under the
' terms of the Apache License Version 2.0 which is available at
' https://www.apache.org/licenses/LICENSE-2.0
'
' SPDX-License-Identifier: Apache-2.0

@startuml
title Version Registration Function

participant "Application\nStartup" as APP
participant "Version\nRegistration\nFunction" as VREG
participant "HTTP Server\n(Axum)" as HTTP

APP -> VREG : register_version_endpoints(\nvendor_name, implementation_version,\ncommit, build_date)
activate VREG

VREG -> VREG : determine base_uri\nand api_version

VREG -> HTTP : register GET /version-info
activate HTTP
HTTP -> VREG : registered
deactivate HTTP

alt optional vendor-specific endpoints enabled
    VREG -> HTTP : register GET /data/version
    activate HTTP
    HTTP -> VREG : registered
    deactivate HTTP

    VREG -> HTTP : register GET /apps/sovd2uds/data/version
    activate HTTP
    HTTP -> VREG : registered
    deactivate HTTP
end

VREG -> APP : registration complete
deactivate VREG

== Runtime: Client requests version info ==

participant Client

Client -> HTTP : GET /version-info
activate HTTP
HTTP -> Client : HTTP 200 OK\n{ "sovd_info": [ { "version": "...",\n"base_uri": "...", "vendor_info": { ... } } ] }
deactivate HTTP

@enduml

Note

The current implementation only registers /data/version and /apps/sovd2uds/data/version

3.3.10. Error Codes & Messages

Note

todo define