{
  "openapi": "3.0.3",
  "info": {
    "title": "Lifecycle Management Issuer API",
    "description": "## Disclaimer\r\nThis specification is currently in Preview.\r\nWhile the core principle will remain, it remains subject to change.\r\n\r\n# Lifecycle Management API\r\n\r\nThis document specifies the standard REST API interface that allows an Issuer's backend to manage the lifecycle of documents (credentials).  \r\nIt enables to update the state and attributes of **single** or **multiple** credentials/deviceCredentials, as well as to send direct ad-hoc messages to end-users without performing an update.  \r\n \r\n# General information\r\n\r\n## Authentication\r\n\r\nTwo methods of authentication can be enabled:\r\n\r\n- Authentication through OAuth2\r\n  - IDEMIA only supports the client secret authentication method for OAuth2\r\n\r\n- Mutual Authentication Using TLS (Transport Layer Security) also referred to as mTLS (mutual Transport Layer Security)\r\n  - For mTLS, IDEMIA will supply the required certificates to secure the connection.\r\n\r\nIn addition to the selected authentication method, each API request must include an API key. The API key is used to identify the tenant and retrieve the corresponding tenant configuration from the backend before request processing continues.\r\n\r\n## General REST API Conventions\r\n\r\nAll interfaces between Lifecycle Management API and Issuer's backend will use a REST API with a JSON payload. \r\n\r\n###\tHTTP Verbs\r\nRESTful Lifecycle Management API tries to adhere as closely as possible to standard HTTP and REST conventions in its use of HTTP verbs.\r\n\r\nTable 1. HTTP Verbs\r\n\r\n\r\n|Verb              |Usage            |\r\n|:-----------------:|:-----------------|\r\n|**GET**|Used to retrieve a resource like to receive bulk query result in the Lifecycle Management API v1. Not used in Lifecycle Management API v2|\r\n|**POST**|Used to request that the origin server accept the entity attached in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. The type of the body of the request is indicated by the Content-Type header.|\r\n\r\n\r\n### HTTP Status Codes\r\nAll interfaces between the Lifecycle Management API and Issuer's Backend will use a REST API with a JSON payload. REST APIs support standard HTTP/HTTPS error codes.\r\n\r\nTable 2. HTTP Status Codes\r\n\r\n|Status Code|Usage                  |\r\n|-----------|-----------------------|\r\n|**1xx** |Informational|\r\n|**2xx** |Success – Standard 200 indicates OK, 202 - request has been accepted |\r\n|**3xx** |Redirection|\r\n|**4xx** |Client Error|\r\n|**400** |Bad request -the request could not be processed because it was malformed or missing one or more mandatory fields.|\r\n|**401** |The Authorization header is missing or token verification failed|\r\n|**403** |The verified client lacks permission to access resource|\r\n|**404** |Identity not found.|\r\n|**5xx** |Server Error|\r\n\r\n\r\n### HTTP Headers\r\n\r\nUpdate Service (Lifecycle Management API) uses a correlation Id in the HTTP header of its REST interfaces to act as a reference for a specific transaction and its related event chain. Each request or message includes this correlation Id. We strongly recommend that customers implementing REST make use of this field, as it helps track transactions across different systems.\r\n\r\nPlease note that different header names and correlation ID formats are used in API versions v1 and v2.\r\n\r\n#### Correlation Id\r\n\r\nThe Correlation Identifier is used to support distributed tracing of requests across services and systems. It allows operators, an Issuer's backend to track the lifecycle of a request and its related events from initiation to completion.\r\n\r\nIn the **Lifecycle Management v2 API**, the correlation mechanism has been standardized to improve interoperability and reliability - instead of using `x-correlation-id`, the request header `x-requestId` is now required.\r\n\r\n**Example:** `x-requestId: 434b05a4-510e-4589-8d5c-73d7333c3f2a`\r\n\r\nThe handling of correlation identifiers has evolved between API versions:\r\n- **In the Lifecycle Management v1 API**, the header `x-correlation-id` was used for request tracing.\r\nThe requirements for this field were not strict.\r\nThe value could be either:\r\n\r\n    - a UUID, or\r\n\r\n    - a comma-separated list of source/value pairs in the format:\r\n    `[value as UUID];source=[source]`\r\n\r\n    This approach offered flexibility but also led to inconsistencies in how identifiers were generated and used.\r\n\r\n- **In the Lifecycle Management v2 API**, the correlation mechanism has been standardized to improve interoperability and reliability - instead of using `x-correlation-id`, the request header `x-requestId` is now required.\r\n\r\n  The value of must be a UUID string in the canonical format (36 characters, including hyphens). If the header is omitted or provided as an empty value, an internal `x-requestId` will be generated.\r\n\r\n  Clients using this header can trace the journey of a request through events (`x-requestId` = `correlationID` in event's header) and finally correlate it with the result of an update.\r\n\r\n  This stricter definition ensures consistency across services and simplifies distributed request tracing.\r\n\r\n\r\n## Motivations for Introducing Lifecycle Management API v2\r\nAPI v1 was designed for a single credential, single device world.\r\n\r\nAPI v2 is required to fully align with the new Wallet model and Wallet partner integration.\r\n\r\nIt allows modernizing the API to align with an asynchronous event driven pattern.\r\n\r\nAPI v2 modernizes lifecycle operations by adopting an asynchronous, event-driven design. It provides a scalable and consistent mechanism for managing credential and device credential state changes, including support for both singleton and batch processing.\r\n\r\nBoth API versions remain relevant within their respective scopes. New integrations that require credential or device state management should use **API v2**, while **API v1** continues to support specific functional scenarios such as attribute updates without a central document registry and ad-hoc messaging.\r\n\r\n## Scope of change - v2 versus v1 API\r\n\r\nV2 API takes the V1 API as a basic structure but enhances it in the following fashion:\r\n\r\n### General changes\r\n  * Normalized API to separate state update from attribute update for both batch and singleton update\r\n  * Simplified batch updates for state changes\r\n  * Event driven alignment\r\n    + Added request identifiers to support distributed tracing and event correlation.\r\n    + Asynchronous confirmation for both singleton and batch updates.\r\n    + All API acknowledges reception when the event is written in our event hub or batch is persisted\r\n    + An asynchronous callback in the form of events is provided for both successful and failure cases for both singleton and batch APIs.\r\n    + Each related events will hold the ``x-requestId`` value as correlation identifier. This means that the ``x-requestId`` from the request header sent to `did-update` will be used as the ``correlationId`` in events triggered by this request. The ``x-requestId`` should be provided in UUID format. If x-requestId is not sent, the correlationId will be generated according to the configuration, which is typically `tcn`. The Istio ``traceId`` is not a UUID.\r\n  * Aligned nomenclature with the multi Wallet model\r\n### Attribute change notification\r\n  * Added ability to convey attribute update scope of change.\r\n    + Each attribute field will need to be identified as ADDED/UPDATED/DELETED.\r\n### Status update\r\n  * Normalized state options to align to the new Wallet model.\r\n  * Added ability to support target specific Wallet ecosystem.\r\n  * Added ability to convey state change reason code.\r\n\r\n## Terminology\r\n\r\n### Credential\r\nRepresents a physical identity document in the DC platform\r\n\r\nThere’s a 1:1 mapping with a DL / ID card or any other issued physical document\r\n\r\nA credential has a credentialID which is a UUID generated at first issuance within a wallet\r\n\r\n### Datagroup\r\nBinary bundle holding a representation of a credential\r\nUsually holds:\r\n* User Identity attributes\r\n* Optionally: Privilege attributes\r\n* A device authentication public key\r\n* Issuer digital signature traceable to a trusted Issuer\r\n\r\nExample: ISO 18013-5 datagroup\r\n### Device\r\nWallet client application instance holding a Digital Credential installed on the end-user physical device.\r\n\r\nA device is identified by a deviceID.\r\nThis identifier identifier the Wallet client application\r\n### DeviceCredential\r\nRepresents an instance of a credential for a given Device.\r\n\r\nA set of datagroups will be issued for each DeviceCredentials.\r\n\r\n### ClientType\r\nClient Type refers to the Wallet client type. This allows the issuer to be informed which Wallet a credential is being issued to.\r\n\r\n",
    "version": "1.0.0"
  },
  "servers": [{ "url": "https://dc-api.app.dev.identity-dev.idemia.io/" }],
  "security": [{ "bearer-token": [] }, { "mutual-tls": [] }],
  "tags": [
    { "name": "Ad Hoc Messaging", "description": " Send Notification to User" },
    {
      "name": "V1 Singleton Update",
      "description": "V1 Singleton Update Operations"
    },
    {
      "name": "Singleton/Batch State Update",
      "description": "State Update Operations V2"
    }
  ],
  "paths": {
    "/v1/notification/send": {
      "post": {
        "tags": ["Ad Hoc Messaging"],
        "summary": "Sends custom notification to mID user through notification service",
        "description": "A custom message from the issuer to the mobile app",
        "operationId": "sendNotification",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdHocNotificationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Successfully queued notification for sending"
          },
          "400": {
            "description": "Bad request: one or more required values are missing"
          },
          "500": { "description": "Internal server error" }
        }
      }
    },
    "/api/v2/updates/state": {
      "post": {
        "tags": ["Singleton/Batch State Update"],
        "summary": "Singleton State Update Request",
        "operationId": "updateStatusV2",
        "parameters": [
          {
            "name": "x-requestId",
            "in": "header",
            "description": "Request Identifier to allow distributed tracing. It is translated to correlationId in the triggered events. Format expected is UUID, must be exactly 36 characters long. In case if empty, internal traceId will be generated and used in events.",
            "required": true,
            "schema": { "type": "string", "maxLength": 36, "minLength": 36 },
            "example": "434b05a4-510e-4589-8d5c-73d7333c3f2a"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/StatusUpdateRequestV2" }
            }
          },
          "required": true
        },
        "responses": {
          "202": { "description": "Accepted" },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorBody" }
              }
            }
          },
          "429": { "description": "Backpressure signal" },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorBody" }
              }
            }
          },
          "503": { "description": "Service Unavailable" }
        }
      }
    },
    "/api/v2/updates/state/batch": {
      "post": {
        "tags": ["Singleton/Batch State Update"],
        "summary": "Batch State Update Request",
        "description": "Bulk request is built of single state updates, closed in ``updates`` array.\n\nBatch is processed on schedule - scheduler is configured per tenant.",
        "operationId": "batchStatusUpdateV2",
        "parameters": [
          {
            "name": "x-requestId",
            "in": "header",
            "description": "Request Identifier to allow distributed tracing. It is translated to correlationId in the triggered events. Format expected is UUID, must be exactly 36 characters long. In case if empty, internal traceId will be generated and used in events.",
            "required": true,
            "schema": { "type": "string", "maxLength": 36, "minLength": 36 },
            "example": "434b05a4-510e-4589-8d5c-73d7333c3f2a"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StatusBatchUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": { "description": "Accepted" },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorBody" }
              }
            }
          },
          "429": { "description": "Backpressure signal" },
          "500": {
            "description": "Internal error",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorBody" }
              }
            }
          },
          "503": { "description": "Service Unavailable" }
        }
      }
    },
    "/api/v1/updates/id/attribute": {
      "post": {
        "tags": ["V1 Singleton Update"],
        "summary": "Update Attributes in projects without central System of Record",
        "description": "[no-SOR] Apply the specified attributes update to the Digital Credential.",
        "operationId": "updateStatusAndOrAttributesForNoSor",
        "parameters": [
          {
            "name": "x-correlation-id",
            "in": "header",
            "description": "Correlation Identifier to allow distributed tracing. It is translated to correlationID in the triggered events. Format expected is UUID. In case if empty, internal traceId will be generated and used in events. Optionally, additional information can be appended after the UUID, separated by a semicolon.",
            "required": false,
            "schema": { "type": "string" },
            "examples": {
              "UUID only": {
                "description": "UUID only",
                "value": "46b5a690-847c-11e8-adc0-fa7ae01bbebc"
              },
              "UUID with additional information": {
                "description": "UUID with additional information",
                "value": "46b5a690-847c-11e8-adc0-fa7ae01bbebc; source=tcn"
              }
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttributeUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK: Update applied successfully",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/DidResponse" }
              }
            }
          },
          "400": {
            "description": "Bad Request: Invalid attribute or invalid status."
          },
          "401": { "description": "Valid bearer token required" },
          "403": {
            "description": "Bearer not authorized to update given update scope"
          },
          "404": {
            "description": "Digital Credential not found for given lookup number"
          },
          "500": { "description": "Internal server error" },
          "503": { "description": "Service Unavailable" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AdHocNotificationRequest": {
        "type": "object",
        "properties": {
          "documentId": {
            "type": "string",
            "description": "The identifier corresponding to the credential or credential instance to receive the message. \nThe type of identifier is specified in identifierType. \n\nBy default, if identifierType is empty, this field is treated as number of physical document.",
            "example": "ST123456"
          },
          "title": {
            "type": "string",
            "description": "Title of the ad hoc message, for example, a short heading for the message.",
            "example": "Day Without a Car Celebration"
          },
          "body": {
            "type": "string",
            "description": "Body of notification",
            "example": "We’re excited to inform you about an upcoming promotion: “Day Without a Car! Tomorrow, in celebration of sustainable mobility, you’ll be able to use public transportation in Aurevia County — completely free of charge. Leave the car at home and join us in making a greener city!",
            "maxLength": 4000,
            "minLength": 0
          },
          "messageType": {
            "type": "string",
            "description": "Reason type for the message.\n\nType of message - contract between sender and receiver. Not validated by any fabric/did component. \n\nTo send ad-hoc message messageType should be INFO. \n\nTo send technical ad-hoc message must be different from the system types. The system types: \n- INFO \n- REGISTER \n- CONSENT \n- CLAIMS \n- UPDATE \n- UNKNOWN \n- CANCEL \n- REINSTATE \n- DELETE \n- DATAGROUP_UPDATE",
            "example": "INFO"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": { "type": "string" },
            "description": "Map of metadata, place for additional properties.",
            "example": { "otp": "SOME_OTP_VALUE", "silent": true }
          },
          "identifierType": {
            "type": "string",
            "description": "Document identifier type, used to recognize Digital Credential. If blank then identifierType is considered as documentId",
            "enum": ["documentId", "midUid", "credentialId"],
            "example": "documentId"
          }
        },
        "required": ["documentId", "messageType"]
      },
      "StatusUpdateRequestV2": {
        "type": "object",
        "description": "Digital Credential status update request V2 specific for a single credential.",
        "properties": {
          "tenantId": {
            "type": "string",
            "description": "Identifier of tenant. This field does not need to be filled in, it will be automatically overwritten with values from headers.",
            "example": "ST"
          },
          "recordIdentifier": {
            "type": "string",
            "description": "Primary identifier for the credential to update.",
            "example": "0267c4c7-ca58-4be1-9a18-85f8993a8f1b",
            "minLength": 1
          },
          "recordIdentifierType": {
            "type": "string",
            "default": "credentialId",
            "description": "Identifier type used for the update.\n\n| RecordIdentifierType | Description  |\n|----------------|--------------|\n|midUid|Unique identifier of the device credential (instance of credential for a given device)|\n|documentId|Identifier of the original physical document, used as a search criteria (backwards compatibility to support issuers not integrated through events propagation|\n|credentialId| Unique identifier of credential; credentialId values returned in the mIDIssued event and will be used as search criteria|",
            "example": "credentialId"
          },
          "customMessage": {
            "type": "string",
            "description": "Optional message  from the Issuer to the mobile app. \n\n **Note:** Applicable for ID Wallet apps only (IDEMIA client types).",
            "example": "Please give us a call at (555)555-5555",
            "maxLength": 512
          },
          "state": {
            "type": "string",
            "description": "Requested credential state.",
            "enum": ["REINSTATED", "SUSPENDED", "REVOKED", "APPROVED"]
          },
          "reason": {
            "type": "string",
            "description": "Optional;\n\nReason code to outline the reason of the state change.\nThese codes are purely informational and will not affect processing.\n\nThese codes will be conveyed to wallet clients partners\n\nThe set of available reason code depends on the state provided and must align.\n\nNote:\n1. The Reason codes are subject to evolve\n2. The Reason codes will be treated as strings an no validation will be performed API level allowing custom codes to be used",
            "oneOf": [
              {
                "type": "string",
                "description": "RevocationReason - The Following reason codes further specifies the reason for Revocation.",
                "enum": [
                  "CREDENTIAL_EXPIRED",
                  "CREDENTIAL_CANCELLED",
                  "WRONGFUL_PROVISION",
                  "DUPLICATE_MDL",
                  "FAKE_CREDENTIAL",
                  "OTHER_FRAUD_CONFIRMED",
                  "FRAUD_STOLEN_IDENTITY",
                  "FRAUD_SYNTHETIC_IDENTITY",
                  "CUSTOMER_INITIATED",
                  "ISSUER_INITIATED",
                  "OTHER"
                ],
                "title": "Revocation reason"
              },
              {
                "type": "string",
                "description": "SuspensionReason - The Following reason codes further specifies the reason for Suspension.",
                "enum": [
                  "STOLEN_IDENTITY_SUSPECTED",
                  "SYNTHETIC_IDENTITY_SUSPECTED",
                  "OTHER_FRAUD_SUSPECTED",
                  "CUSTOMER_INITIATED",
                  "ISSUER_INITIATED",
                  "DEVICE_LOST_OR_STOLEN",
                  "OTHER"
                ],
                "title": "Suspension reason"
              },
              {
                "type": "string",
                "description": "ReinstatementReason - The Following reason codes further specifies the reason for Reinstatement.",
                "enum": [
                  "FRAUD_INVESTIGATION_COMPLETE",
                  "OTHER_INVESTIGATION_COMPLETE",
                  "ISSUER_ISSUE_RESOLVED",
                  "CUSTOMER_ISSUE_RESOLVED",
                  "OTHER"
                ],
                "title": "Reinstatement reason"
              }
            ]
          },
          "clientType": {
            "type": "string",
            "description": "Optional field to affect only specific client wallet types. If not present, **all** client wallet types will be affected.",
            "example": "IDEMIA"
          },
          "targetRecordTypes": {
            "type": "array",
            "description": "An optional parameter provides the ability to alter state for credential and deviceCredential independently.\n\n\nThe default value is targeting both - credential and deviceCredential.\n\n\n1. Providing only 'CREDENTIAL' indicates a change of the credential state only - update on the backend only.\n\n2. 'DEVICE_CREDENTIAL' means changes concerning deviceCredentials status on backend and in the end-user application - the credential state remains unchanged.\n\n3. Specifying both values 'CREDENTIAL', 'DEVICE_CREDENTIAL' results in state update of the credential and its associated deviceCredentials.\n\nList of:\n\nRecordType:\n\n  type: array\n\n  default: [\"CREDENTIAL\", \"DEVICE_CREDENTIAL\"]\n\n  items:\n\n    type: string\n\n    enum:\n\n      - \"CREDENTIAL\"\n\n      - \"DEVICE_CREDENTIAL\"\n",
            "items": {
              "type": "string",
              "enum": ["CREDENTIAL", "DEVICE_CREDENTIAL"]
            }
          }
        },
        "required": ["recordIdentifier", "state"]
      },
      "ErrorBody": {
        "type": "object",
        "properties": {
          "errorCode": {
            "type": "string",
            "description": "ErrorCode to identify the error reason.\n\nThe INVALID_REQUEST will be provided with a message capturing the list of fields that are conflicting with the defined schema.\n\nThe enum list may be expanded.",
            "enum": [
              "INVALID_REQUEST",
              "INTERNAL_ERROR",
              "SERVICE_UNAVAILABLE"
            ],
            "example": "INVALID_REQUEST"
          },
          "message": {
            "type": "string",
            "description": "Error message containing details about error",
            "example": "recordIdentifier is missing"
          }
        },
        "required": ["errorCode", "message"]
      },
      "StatusBatchUpdateRequest": {
        "type": "object",
        "properties": {
          "updates": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/StatusUpdateRequestV2" }
          }
        }
      },
      "AttributeUpdateRequest": {
        "type": "object",
        "description": "A credential or device credential attributes update request specific to a single Digital Credential.",
        "properties": {
          "documentId": {
            "type": "string",
            "description": "Identifier of the Digital Credential to update.",
            "example": "0267c4c7-ca58-4be1-9a18-85f8993a8f1b",
            "minLength": 1
          },
          "status": {
            "type": "string",
            "description": "This field need to be empty. \n\nIf blank, the request is for attribute updates only."
          },
          "attributes": {
            "type": "object",
            "additionalProperties": { "type": "string" },
            "description": "The attributes being updated.",
            "example": { "firstName1": "John" }
          },
          "customMessage": {
            "type": "string",
            "description": "A custom message - direct communication with the Digital Credential holder",
            "example": "Have a nice day today!",
            "maxLength": 512
          },
          "identifierType": {
            "type": "string",
            "default": "documentId",
            "description": "Identifier type used for the update.\n\n| RecordIdentifierType | Description  |\n|---------------|--------------|\n|midUid|Unique identifier of the device credential (instance of credential for a given device)|\n|documentId|Identifier of the original physical document, used as a search criteria (backwards compatibility to support issuers not integrated through events propagation|\n|credentialId|Unique identifier of credential; the credentialId values returned in the **mIDIssued** event, can be used as search criteria|",
            "example": "credentialId"
          }
        },
        "required": ["documentId"]
      },
      "DidResponse": {
        "type": "object",
        "properties": {
          "resultCode": {
            "type": "string",
            "enum": [
              "SUCCESS",
              "CREATED",
              "CONFLICT",
              "SPRING_VALIDATION_ERROR",
              "REQUEST_ENDPOINT_NOT_IMPLEMENTED",
              "BAD_REQUEST",
              "AUTHENTICATION_ERROR",
              "AUTHORIZATION_ERROR",
              "INTERNAL_SERVER_ERROR",
              "SERVICE_UNAVAILABLE",
              "FORBIDDEN",
              "NOT_FOUND",
              "CORRELATION_ID_MISSING",
              "CORRELATION_ID_CONFLICT",
              "CORRELATION_ID_MALFORMED",
              "MESSAGE_QUEUE_SEND_ERROR",
              "MESSAGE_QUEUE_RECEIVE_ERROR",
              "MESSAGE_QUEUE_ERROR",
              "MESSAGE_DECRYPT_EXCEPTION",
              "MESSAGE_DECRYPT_CONTENT_MALFORMED",
              "MESSAGE_DECRYPT_KEY_EXCEPTION",
              "MESSAGE_DECRYPT_KEY_NOT_FOUND",
              "MESSAGE_DECRYPT_UNSUPPORTED_CONTENT_TYPE",
              "MESSAGE_DECRYPT_ERROR",
              "MESSAGE_ENCRYPT_EXCEPTION",
              "MESSAGE_ENCRYPT_KEY_EXCEPTION",
              "MESSAGE_ENCRYPT_KEY_NOT_FOUND",
              "MESSAGE_ENCRYPT_ERROR",
              "MESSAGE_ENCRYPTION_CONTENT_TYPE_REQUIRED",
              "MESSAGE_ENCRYPTION_ACCEPT_REQUIRED",
              "MESSAGE_ENCRYPTION_SERVICE_NAME_REQUIRED",
              "MESSAGE_ENCRYPTION_POLICY_UNFULFILLED",
              "MESSAGE_ENCRYPTION_MISCONFIGURED",
              "DECRYPT_INVALID_SIGNATURE",
              "DECRYPT_MISSING_JWT",
              "DECRYPT_ERROR",
              "ENCRYPT_ERROR",
              "PUBLIC_KEY_MISSING",
              "PRIVATE_KEY_MISSING",
              "HASH_INVALID_SALT",
              "NO_ALIAS",
              "CERTIFICATE_ERROR",
              "SIGNING_ERROR",
              "PUBLIC_KEY_MALFORMED",
              "JWT_SIGNATURE_INVALID",
              "JWT_VERIFICATION_ERROR",
              "JWT_MALFORMED",
              "JWT_MISSING",
              "JWT_CLAIMS_NOT_FOUND",
              "JWT_SIGNATURE_ALGORITHM_UNSUPPORTED",
              "JWT_SIGNATURE_VERIFIER_INIT_ERROR",
              "JWT_ERROR",
              "INVALID_ACCESS_TOKEN",
              "OAUTH_INIT_ERROR",
              "ENCRYPTED_CACHE_ERROR",
              "MERKLE_TREE_VALIDATION_ERROR",
              "MERKLE_TREE_MERGE_ERROR",
              "MERKLE_TREE_ERROR",
              "DATA_GROUPS_INVALID_REQUEST",
              "MSO_VALIDATION_ERROR",
              "MSO_CERTIFICATE_ERROR",
              "MSO_ERROR",
              "SCIM_AUTH_ERROR",
              "SCIM_AMBIGUOUS_PERSON",
              "SCIM_AMBIGUOUS_DEVICE",
              "SCIM_PERSON_NOT_FOUND",
              "SCIM_DEVICE_NOT_FOUND",
              "SCIM_DEVICE_NOT_FOUND_FORBIDDEN",
              "SCIM_ATTRIBUTE_NOT_FOUND",
              "SCIM_OBJECT_NOT_FOUND",
              "SCIM_INIT_ERROR",
              "SCIM_ERROR",
              "JSON_PARSING_ERROR",
              "JSON_MAPPING_ERROR",
              "JSON_IO_ERROR",
              "JSON_ERROR",
              "YAML_IO_ERROR",
              "DATA_VALIDATION",
              "REQUIRED_ATTRIBUTE_MISSING",
              "REQUIRED_ATTRIBUTE_BLANK",
              "UNSUPPORTED_ATTRIBUTE",
              "REQUIRED_MEDIA_MISSING",
              "INVALID_JURISDICTION_ID",
              "INVALID_DATE_FORMAT",
              "ATTRIBUTES_MATCHING_RULES_NOT_FOUND",
              "USER_PORTRAIT_NOT_FOUND",
              "MATCHING_PROVIDER_ERROR",
              "SOR_CONNECTION_ERROR",
              "SOR_SERVICE_ERROR",
              "CONTEXT_SERVICE_ERROR",
              "CONTEXT_SERVICE_USER_NOT_FOUND_ERROR",
              "CONTEXT_BAD_REQUEST",
              "CONTEXT_ERROR",
              "CONTEXT_ALL_SOR_CALLS_FAILED",
              "CONTEXT_MULTIPLE_SOR_CALLS_FAILED",
              "CONTEXT_MULTIPLE_SOR_CALLS_SUCCEEDED",
              "ISSUANCE_KEYS_EXPIRED",
              "ISSUANCE_KEYS_DECRYPTION_EXCEPTION",
              "ISSUANCE_UNSATISFIED_ATTRIBUTE",
              "ISSUANCE_RESULT_SIGNING_FAILED",
              "ISSUANCE_RESULT_ENCRYPTION_EXCEPTION",
              "ISSUANCE_ERROR",
              "REGISTER_REQUEST_USER_INACTIVE",
              "ISSUANCE_TOO_MANY_REQUESTS",
              "EWA_CLAIM_GENERATION_ERROR",
              "EWA_CLAIM_VERIFICATION_ERROR",
              "MATCHING_ASSERTION_EXPIRED_ERROR",
              "MATCHING_ASSERTION_INVALID",
              "CREDENTIALID_MISMATCH",
              "ELIGIBILITY_CHECK_FAILURE",
              "ISSUING_AUTHORITY_INVALID_REQUEST",
              "ISSUING_AUTHORITY_VERIFIED_CLAIM_VALIDATION_ERROR",
              "ISSUING_AUTHORITY_VERIFIED_CLAIM_CONTENT_ERROR",
              "ISSUING_AUTHORITY_ERROR",
              "UPDATE_REQUEST_INVALID_STATUS",
              "UPDATE_REQUEST_MESSAGE_EXCEEDS_MAX_LENGTH",
              "BULK_UPDATE_BAD_REQUEST",
              "BULK_UPDATE_TICKET_NOT_FOUND",
              "BULK_ERROR",
              "SMS_EXTERNAL_MESSAGING_SERVICE_EXCEPTION",
              "SMS_USER_NOT_FOUND",
              "SMS_USER_OPTED_IN",
              "SMS_USER_OPTED_OUT",
              "SMS_USER_PERSISTENCE_EXCEPTION",
              "SMS_PHONE_NUMBER_PARSING_EXCEPTION",
              "SMS_ERROR",
              "FACE_IMAGE_DIMENSIONS_INVALID",
              "FACE_IMAGE_EMPTY",
              "FACE_IMAGE_INVALID",
              "FACE_GENERATOR_INIT_FAILED",
              "FACE_GENERATOR_HANDLE_NULL",
              "FACE_GENERATOR_ILLEGAL_ARGUMENT",
              "FACE_GENERATOR_SDK_LOAD_FAILED",
              "FACE_GENERATOR_ADD_LICENSE_FAILED",
              "FACE_ERROR",
              "RENDER_DOCUMENT_NOT_FOUND",
              "RENDER_UNABLE_TO_RESOLVE_DOCUMENT_VERSION",
              "RENDER_ERROR",
              "CONSENT_REQUEST_EXPIRED",
              "CONSENT_ID_MISMATCH",
              "CONSENT_REQUEST_NOT_FOUND",
              "CONSENT_REQUEST_USER_INACTIVE",
              "CONSENT_EXTERNAL_CALLBACK_ERROR",
              "CONSENT_ERROR",
              "NOTIFICATION_NOT_FOUND",
              "NOTIFICATION_ERROR",
              "NOTIFICATION_EXPIRED",
              "APPLICATION_ID_INVALID",
              "DOCUMENT_NOT_FOUND",
              "DOCUMENT_CACHE_ERROR",
              "DOCUMENT_LAST_FAILURE",
              "DOCUMENT_LIST_FAILURE",
              "DOCUMENT_COUNT_FAILURE",
              "DOCUMENT_ARTIFACT_LIST_FAILURE",
              "DOCUMENT_ARTIFACT_COUNT_FAILURE",
              "DOCUMENT_ERROR",
              "CLAIMS_NOT_FOUND",
              "CLAIMS_ERROR",
              "CLAIMS_CACHE_ENTRY_NOT_FOUND",
              "REALID_CONSUMER_MESSAGE_TYPE_MISSING",
              "REALID_CONSUMER_MESSAGE_VERSION_MISSING",
              "REALID_CONSUMER_INVALID_MESSAGE",
              "IM_IDENTITY_NOT_FOUND",
              "IM_IDENTITY_CONFLICT",
              "IM_EVENT_CONFLICT",
              "IM_EVENT_NOT_FOUND",
              "IM_CREDENTIAL_NOT_FOUND",
              "IM_DEVICE_CREDENTIAL_NOT_FOUND",
              "IM_INVALID_REQUEST",
              "FACECHECK_INVALID_MESSAGE",
              "FACECHECK_ERROR",
              "IAM360_SESSION_NOT_FOUND",
              "IAM360_USER_VALIDATION_FAILURE",
              "IAM360_SESSION_CONFLICT",
              "NO_ELIGIBLE_CREDENTIAL_FOUND",
              "SUBSTANTIAL_REQUEST_PERSON_NOT_FOUND",
              "CAMEL_INIT_ERROR",
              "UNKNOWN_ERROR",
              "CREATE_EVENT_ERROR",
              "WRONG_TYPE_EVENT_ERROR",
              "READ_EVENT_ERROR",
              "KAFKA_REST_CONNECTION_ERROR",
              "KAFKA_REST_PARSING_ERROR",
              "CANNOT_RETRIEVE_CERTIFICATE",
              "CANNOT_RENEW_CERTIFICATE",
              "INVALID_PRIVATE_KEY",
              "SIGNATURE_FAILURE",
              "TENANT_NOT_FOUND",
              "USER_NOT_FOUND",
              "USER_CONFLICT",
              "MID_REPO_INVALID_REQUEST",
              "DEVICE_LIMIT_REACHED",
              "WALLET_CONSISTENCY_FAILURE"
            ]
          },
          "message": { "type": "string" }
        }
      }
    },
    "securitySchemes": {
      "mutual-tls": {
        "type": "mutualTLS",
        "description": "Authentication via mutual TLS (client certificate required)"
      },
      "bearer-token": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  }
}
