{
  "openapi": "3.0.0",
  "info": {
    "title": "UNTP Identity Resolver API",
    "description": "Implementation guidance for the UNTP Identity Resolver (IDR) specification. This API implements the Discover-Resolve-Verify workflow defined by the UNTP IDR specification, enabling supply chain actors to resolve product and facility identifiers from **any** registered identifier scheme to linked digital credentials such as Digital Product Passports (DPPs), Digital Conformity Credentials (DCCs), Digital Facility Records (DFRs), and Digital Traceability Events (DTEs).\n\nUNTP does not mandate GS1. Identifier key types, path shape, and optional multi-segment (\"qualifier\") paths are defined per scheme. GS1 Digital Link is one supported encoding; ISO/IEC 15459 with ASC MH10 Data Identifiers, opaque registry IDs, Identification Links, and other EN 18219-aligned families are equally valid when registered as namespaces.\n\n## Standards Compliance\n\n- **ISO/IEC 18975** — Encoding and resolving identifiers over HTTP\n- **IETF RFC 9264** — Linkset media type for typed link collections\n- **W3C DID Resolution** — Decentralised identifier resolution patterns\n- **IETF RFC 8615** — Well-known URI discovery mechanism\n\n## Functional Layers\n\nThe API is organized into three functional layers:\n\n1. **Resolution (public)** — Anonymous, unauthenticated resolution of identifiers to linksets or redirects. This is the core conformity surface that supply chain verifiers interact with.\n2. **Link Registration (management)** — Authenticated API for registering and managing link resolver entries that associate identifiers with typed link targets.\n3. **Identifier Scheme Management** — Authenticated API for configuring permitted identifier schemes (namespaces and application identifiers) before link registration can occur.\n\n## Normative Requirements\n\nThis API addresses UNTP IDR normative requirements IDR-01 through IDR-14. Key requirements include: IDR-01 (identifier scheme registration), IDR-02 (link registration), IDR-06/07/08 (resolution with link type, language, and context negotiation), IDR-09 (optional scheme-defined path grouping), IDR-10 (secure targets with encryption and access roles), and IDR-14 (resolver description discovery).",
    "version": "1.0.0"
  },
  "tags": [
    {
      "name": "Link Resolution",
      "description": "Public, anonymous resolution of identifiers to linksets or redirect targets. Implements IDR-06, IDR-07, and IDR-08. Resolution paths conform to ISO/IEC 18975 structured-path URI syntax when the scheme uses that encoding: /{namespace}/{identifierKeyType}/{identifierKey}/{optionalSchemeSegments}. identifierKeyType is a **scheme-defined** shortcode (e.g. gtin, 25S, product, facility) — not a mandatory GS1 Application Identifier. Optional trailing path segments (historically called \"qualifiers\" in GS1) are scheme-specific; leave them empty when the scheme uses an opaque single-segment ID. The same path applies to products, facilities, and other entity types; facility identifiers typically omit the trailing segments (empty secondaryIdentifiersPath)."
    },
    {
      "name": "Link Registration",
      "description": "Authenticated API for registering link resolver entries that associate an identifier with one or more typed link targets (the responses array). Each entry represents one identified item with multiple link variants differentiated by link type, language, MIME type, context, and access role. Implements IDR-02 (one carrier, many links), IDR-09 (qualifier path grouping), and IDR-10 (secure targets)."
    },
    {
      "name": "Link Management",
      "description": "CRUD operations on individual links within a registered resolver entry. Use these endpoints to update target URLs, rotate credentials, change access roles, toggle active status, or soft/hard delete individual link variants without affecting other links on the same identifier."
    },
    {
      "name": "Identifiers",
      "description": "Manage permitted identifier schemes (namespaces and their application identifiers). An identifier scheme must be registered before any link registration can reference it. Each scheme defines a namespace, a set of application identifiers (primary keys, qualifiers, data attributes) with regex validation patterns, and their relationships. Implements IDR-01 (scheme registration), IDR-03 (identifier validation), and IDR-04 (scheme configuration)."
    }
  ],
  "servers": [
    {
      "url": "https://{resolverDomain}/api/{version}",
      "description": "UNTP Identity Resolver API. Replace the variables with your resolver's domain and API version.",
      "variables": {
        "resolverDomain": {
          "default": "resolver.example.com",
          "description": "The domain name of the identity resolver service. Each registry operator deploys their own resolver instance."
        },
        "version": {
          "default": "1.0.0",
          "description": "API version. Follows the UNTP specification version that the resolver implements."
        }
      }
    }
  ],
  "paths": {
    "/health-check": {
      "get": {
        "operationId": "AppController_healthCheck",
        "summary": "Health check",
        "parameters": [],
        "responses": {
          "201": {
            "description": "Health check status",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "status": "OK"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/identifiers": {
      "post": {
        "operationId": "IdentifierManagementController_upsertIdentifier",
        "summary": "Create or update identifier",
        "description": "Registers or updates an identifier scheme configuration. Defines the namespace, application identifiers (primary keys, qualifiers, data attributes), their regex validation patterns, and relationships. An identifier scheme MUST be registered before any link registration can occur for that namespace. If the namespace already exists, the configuration is replaced (upsert semantics).",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdentifierDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Identifier scheme created or updated successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "message": "Application identifier upserted successfully"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error. The request body does not conform to the IdentifierDto schema — for example, missing required fields, invalid regex patterns, or duplicate shortcodes within the same namespace.",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "errors": [
                      {
                        "field": "applicationIdentifiers.0.shortcode",
                        "message": "shortcode must be a string"
                      },
                      {
                        "field": "applicationIdentifiers.0.regex",
                        "message": "regex must be a string"
                      }
                    ]
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "message": "Internal server error"
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Identifiers"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      },
      "delete": {
        "operationId": "IdentifierManagementController_deleteIdentifier",
        "summary": "Delete identifier by namespace",
        "description": "Permanently removes an identifier scheme and all its application identifier configurations. Existing link resolver entries that reference this namespace will no longer resolve.",
        "parameters": [
          {
            "name": "namespace",
            "required": true,
            "in": "query",
            "description": "The namespace of the identifier scheme to delete (e.g. \"gs1\", \"nlis\"). Must match an existing registered scheme.",
            "schema": {
              "type": "string",
              "example": "example-identifier-scheme"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Identifier scheme deleted successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "message": "Application identifier deleted successfully"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "error": "Namespace is required"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "message": "Internal server error"
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Identifiers"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      },
      "get": {
        "operationId": "IdentifierManagementController_getIdentifier",
        "summary": "Get identifier by namespace",
        "description": "Retrieves the configuration for one or all registered identifier schemes. When a namespace is specified, returns that scheme's configuration. When omitted, returns all registered schemes. Useful for inspecting which identifier types and validation patterns are currently configured.",
        "parameters": [
          {
            "name": "namespace",
            "required": false,
            "in": "query",
            "description": "The namespace of the identifier scheme to retrieve (e.g. \"gs1\", \"nlis\"). If not provided, all registered identifier schemes are returned.",
            "schema": {
              "type": "string",
              "example": "example-identifier-scheme"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Identifier scheme(s) retrieved successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/IdentifierDto"
                    },
                    {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IdentifierDto"
                      }
                    }
                  ]
                },
                "examples": {
                  "oneNamespace": {
                    "summary": "Single Namespace Response",
                    "value": {
                      "namespace": "example-identifier-scheme",
                      "applicationIdentifiers": [
                        {
                          "title": "Global Trade Item Number (GTIN)",
                          "label": "GTIN",
                          "shortcode": "gtin",
                          "ai": "01",
                          "type": "I",
                          "qualifiers": [
                            "10"
                          ],
                          "regex": "(\\d{12,14}|\\d{8})"
                        },
                        {
                          "title": "Batch or Lot Number",
                          "label": "BATCH/LOT",
                          "shortcode": "lot",
                          "ai": "10",
                          "type": "Q",
                          "regex": "([\\x21-\\x22\\x25-\\x2F\\x30-\\x39\\x41-\\x5A\\x5F\\x61-\\x7A]{0,20})"
                        }
                      ]
                    }
                  },
                  "allNamespaces": {
                    "summary": "All Namespaces Response",
                    "value": [
                      {
                        "namespace": "example-identifier-scheme",
                        "applicationIdentifiers": [
                          {
                            "title": "Global Trade Item Number (GTIN)",
                            "label": "GTIN",
                            "shortcode": "gtin",
                            "ai": "01",
                            "type": "I",
                            "regex": "(\\d{12,14}|\\d{8})"
                          }
                        ]
                      },
                      {
                        "namespace": "integrity-systems",
                        "applicationIdentifiers": [
                          {
                            "title": "NLIS ID",
                            "label": "NLISID",
                            "shortcode": "nlisid",
                            "ai": "01",
                            "format": "N14",
                            "type": "I",
                            "regex": "(\\d{12,14}|\\d{8})"
                          }
                        ]
                      }
                    ]
                  },
                  "opaqueProductRegister": {
                    "summary": "Non-GS1 opaque product register (no qualifiers)",
                    "value": {
                      "namespace": "products.sample-register.example",
                      "applicationIdentifiers": [
                        {
                          "title": "Opaque product identifier",
                          "label": "PRODUCT",
                          "shortcode": "product",
                          "type": "I",
                          "regex": "[A-Za-z0-9_-]{1,64}"
                        }
                      ]
                    }
                  },
                  "ascMh10SerialisedProduct": {
                    "summary": "Non-GS1 ASC MH10 Data Identifier scheme",
                    "value": {
                      "namespace": "industrial-ids.example",
                      "applicationIdentifiers": [
                        {
                          "title": "Serialised product (ASC MH10 DI 25S)",
                          "label": "25S",
                          "shortcode": "25S",
                          "ai": "25S",
                          "type": "I",
                          "regex": "[A-Za-z0-9]{1,50}"
                        }
                      ]
                    }
                  },
                  "gs1DigitalLink": {
                    "summary": "GS1 Digital Link-style scheme (optional path continuations)",
                    "value": {
                      "namespace": "example-identifier-scheme",
                      "applicationIdentifiers": [
                        {
                          "title": "Global Trade Item Number (GTIN)",
                          "label": "GTIN",
                          "shortcode": "gtin",
                          "ai": "01",
                          "type": "I",
                          "qualifiers": [
                            "10"
                          ],
                          "regex": "(\\d{12,14}|\\d{8})"
                        },
                        {
                          "title": "Batch or Lot Number",
                          "label": "BATCH/LOT",
                          "shortcode": "lot",
                          "ai": "10",
                          "type": "Q",
                          "regex": "([\\x21-\\x22\\x25-\\x2F\\x30-\\x39\\x41-\\x5A\\x5F\\x61-\\x7A]{0,20})"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "message": "Internal server error"
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Identifiers"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      }
    },
    "/resolver": {
      "post": {
        "operationId": "LinkRegistrationController_create",
        "summary": "Register a new link resolver",
        "description": "Registers a link resolver entry associating an identifier with one or more typed link targets. Each entry in the responses array represents a link variant — a combination of link type, language, MIME type, geographic context, and access role — per UNTP IDR-06. This implements the core IDR-02 requirement: one identified item (carrier) linked to many digital credentials and documents.\n\nUpsert semantics: if a resolver entry already exists for the same namespace + identificationKeyType + identificationKey + qualifierPath combination, new responses are added and existing responses with matching linkType + mimeType + context are updated. hreflang is metadata on the variant (not part of the matching key) — a single variant can serve multiple languages.",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLinkRegistrationDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Link resolver entry registered successfully. The identifier is now resolvable via the resolution endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "message": "Link resolver registered successfully"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error. Common causes: the namespace or identificationKeyType is not registered, the identificationKey does not match the registered regex pattern, or required response fields are missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldErrorsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity. The request is syntactically valid but semantically incorrect — for example, a qualifier path that references an AI not registered as a qualifier for the primary identifier type.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldErrorsResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldErrorsResponse"
                }
              }
            }
          }
        },
        "tags": [
          "Link Registration"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      }
    },
    "/resolver/links": {
      "get": {
        "operationId": "LinkManagementController_listLinks",
        "summary": "List all active links for an identifier",
        "description": "Retrieves all active links registered for a specific identifier, optionally filtered by linkType, mimeType, or language. Returns the full link variant details including target URLs, access roles, and encryption metadata. This is a management endpoint for inspecting registered links — for public resolution, use the /{namespace}/{identifierKeyType}/{identifierKey} path instead.",
        "parameters": [
          {
            "name": "namespace",
            "required": true,
            "in": "query",
            "description": "The namespace of the identifier scheme (e.g. \"gs1\", \"nlis\"). Must match a registered identifier scheme.",
            "example": "example-identifier-scheme",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "identificationKeyType",
            "required": true,
            "in": "query",
            "description": "The application identifier shortcode (e.g. \"gtin\", \"nlisid\"). Must be a registered shortcode within the specified namespace.",
            "example": "gtin",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "identificationKey",
            "required": true,
            "in": "query",
            "description": "The actual identifier value (e.g. GTIN digits \"09359502000010\"). Must match the regex pattern registered for this identifier type.",
            "example": "12345678901234",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "qualifierPath",
            "required": false,
            "in": "query",
            "description": "Optional qualifier path segment for sub-identification (e.g. \"/10/LOT123\" for batch). Use \"/\" for the base identifier without qualifiers. Implements IDR-09 logical grouping.",
            "example": "/10/12345678901234567890",
            "schema": {
              "default": "/",
              "type": "string"
            }
          },
          {
            "name": "linkType",
            "required": false,
            "in": "query",
            "description": "Filter results by link type. Use UNTP link relations (e.g. \"untp:dpp\", \"untp:dcc\") or scheme-specific types (e.g. \"gs1:certificationInfo\").",
            "example": "example-identifier-scheme:certificationInfo",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mimeType",
            "required": false,
            "in": "query",
            "description": "Filter results by MIME type of the target resource (e.g. \"application/json\", \"application/vc+ld+json\", \"application/pdf\").",
            "example": "application/json",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hreflang",
            "required": false,
            "in": "query",
            "description": "Filter results by BCP 47 language tag (e.g. \"en\", \"de\", \"ja\"). Returns only link variants whose hreflang array contains the specified tag.",
            "example": "en",
            "schema": {
              "type": "string",
              "pattern": "(^\\w{2}$)|(^\\w{2}-\\w{2}$)"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Links retrieved successfully. Returns an array of link variants matching the query filters."
          },
          "400": {
            "description": "Validation error. The namespace or identificationKeyType is not registered, or required query parameters are missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldErrorsResponse"
                }
              }
            }
          },
          "404": {
            "description": "No link resolver entry found for this identifier. The namespace + identificationKeyType + identificationKey + qualifierPath combination has no registered links."
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "tags": [
          "Link Management"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      }
    },
    "/resolver/links/{linkId}": {
      "get": {
        "operationId": "LinkManagementController_getLink",
        "summary": "Get a specific link by linkId",
        "description": "Retrieves the full details of a single link variant by its server-generated identifier. Returns all properties including target URL, link type, access roles, encryption metadata, and active status.",
        "parameters": [
          {
            "name": "linkId",
            "required": true,
            "in": "path",
            "description": "The server-generated unique identifier for the link variant (UUID format).",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Link variant retrieved successfully."
          },
          "404": {
            "description": "No link found with the specified linkId."
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "tags": [
          "Link Management"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      },
      "put": {
        "operationId": "LinkManagementController_updateLink",
        "summary": "Update a specific link",
        "description": "Updates properties of a single link variant. All fields are optional (partial update semantics) — only the fields included in the request body are modified. Useful for rotating target URLs, changing access roles, toggling active status, or updating encryption methods without recreating the entire resolver entry.",
        "parameters": [
          {
            "name": "linkId",
            "required": true,
            "in": "path",
            "description": "The server-generated unique identifier for the link variant to update (UUID format).",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLinkDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Link variant updated successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "message": "Link updated successfully"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error. Invalid field values — for example, an unrecognised MIME type or malformed target URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldErrorsResponse"
                }
              }
            }
          },
          "404": {
            "description": "No link found with the specified linkId."
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "tags": [
          "Link Management"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      },
      "delete": {
        "operationId": "LinkManagementController_deleteLink",
        "summary": "Delete a specific link (soft by default, hard with ?hard=true)",
        "description": "Removes a link variant. By default, performs a soft delete: the link is deactivated (active=false) and excluded from resolution responses, but retained in storage for audit trail purposes. When hard=true, the link is permanently removed from the database. Soft-deleted links can be reactivated by updating their active status via PUT.",
        "parameters": [
          {
            "name": "linkId",
            "required": true,
            "in": "path",
            "description": "The server-generated unique identifier for the link variant to delete (UUID format).",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hard",
            "required": false,
            "in": "query",
            "description": "Set to true for permanent deletion. When false or omitted, the link is soft-deleted (deactivated but retained for audit).",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Link variant deleted successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "example": {
                    "message": "Link deleted successfully"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No link found with the specified linkId."
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "tags": [
          "Link Management"
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      }
    },
    "/{namespace}/{identifierKeyType}/{identifierKey}/{secondaryIdentifiersPath}": {
      "get": {
        "operationId": "LinkResolutionController_resolveClone",
        "summary": "Resolve a link resolver for an identifier",
        "description": "Core UNTP identity resolution endpoint. Resolves an identifier to its registered link targets.\n\nResolution behaviour depends on the linkType parameter:\n- When linkType is omitted or set to a specific type: returns a **302 redirect** to the default link target URL matching the requested type, language, and context.\n- When linkType is \"all\": returns a **full RFC 9264 linkset** as JSON containing all registered link variants for the identifier.\n\nPath structure (ISO/IEC 18975-style schemes): `/{namespace}/{identifierKeyType}/{identifierKey}/{optionalSegments}`.\n- `namespace` — registered identifier scheme (not limited to GS1).\n- `identifierKeyType` — scheme-defined shortcode for the primary identifier class (e.g. `gtin`, `25S`, `product`). Not mandatory GS1.\n- `identifierKey` — the primary identifier value.\n- `optionalSegments` — empty for opaque IDs; used only when the scheme encodes additional identity in the path (e.g. GS1 serial AI 21).\n\n**Non-GS1 example (opaque product register):** `GET /products.sample-register.example/product/ABC123456/?linkType=all`\n\n**Non-GS1 example (ASC MH10 DI):** `GET /industrial-ids.example/25S/IAC42PROD987654/?linkType=all`\n\n**GS1-style example (optional multi-segment):** `GET /gs1/01/09506000134352/21/SERIAL123?linkType=all`\n\n**Facility example:** `GET /facilities-register/facility/ABC123456/?linkType=all` returns a linkset whose anchor is the facility identifier and whose `dfr` link points to the Facility Record — no product carrier or serial/batch path segments are required.\n\nThis endpoint is public and does not require authentication.",
        "parameters": [
          {
            "name": "namespace",
            "required": true,
            "in": "path",
            "description": "Identifies the identifier scheme (e.g. \"gs1\", \"industrial-ids\", \"products.sample-register.example\", \"nlis\"). Maps to the scheme's registered configuration. Must match a namespace previously registered via the /identifiers endpoint. Not limited to GS1.",
            "example": "products.sample-register.example",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "identifierKeyType",
            "required": true,
            "in": "path",
            "description": "Scheme-defined shortcode or code for the primary identifier class (e.g. \"product\" for an opaque register, \"25S\" for an ASC MH10 Data Identifier, \"01\"/\"gtin\" for GS1 GTIN). Must be a registered shortcode within the specified namespace. GS1 Application Identifiers are one option, not a UNTP requirement.",
            "example": "product",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "identifierKey",
            "required": true,
            "in": "path",
            "description": "The primary identifier value (e.g. opaque register id \"ABC123456\", MH10 value \"IAC42PROD987654\", or GTIN digits). Must match the regex pattern registered for this identifier type in the scheme configuration.",
            "example": "ABC123456",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "secondaryIdentifiersPath",
            "required": true,
            "in": "path",
            "allowEmptyValue": true,
            "description": "Optional scheme-specific path continuation after the primary identifier. Empty for opaque single-segment IDs (typical for many non-GS1 registers) and for typical facility resolution, which reuses the product path structure without serial/batch segments. Used when a scheme encodes additional identity in the path (e.g. GS1 \"21/SERIAL123\"). These segments are part of that scheme's identifier syntax — not a general UNTP qualifier model. Implements optional IDR-09 grouping when the scheme defines it.",
            "example": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "linkType",
            "required": false,
            "in": "query",
            "description": "Filter by link relation type. Use UNTP-defined types (e.g. \"untp:dpp\" for Digital Product Passport, \"untp:dcc\" for Digital Conformity Credential, \"untp:dfr\" for Digital Facility Record, \"untp:dte\" for Digital Traceability Event) or scheme-specific types (e.g. \"gs1:certificationInfo\"). Set to \"all\" to return the full RFC 9264 linkset containing all registered link variants. Implements IDR-07.",
            "example": "all",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accessRole",
            "required": false,
            "in": "query",
            "description": "Variant-based disclosure filtering per IDR-10 (secure targets). Filters resolution results to only include link variants whose accessRole array includes the specified role. Standard UNTP roles: anonymous (default, public access), customer (supply chain partner), regulator (government authority), recycler (end-of-life processor), auditor (conformity assessment body), owner (identifier registrant).",
            "example": "customer",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "decryptionKey",
            "required": false,
            "in": "query",
            "description": "Shared secret for decrypting encrypted content at the target URL. When the matched link variant has fwqs (forward query string) enabled, this key is appended as a query parameter to the target URL on redirect. Supports encrypted credential retrieval per IDR-10 secure targets. Silently ignored when fwqs is disabled for the matched link or when resolution returns a linkset rather than a redirect.",
            "example": "a3f2b8c1d5e6f7a8b9c0d1e2f3a4b5c6",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to the resolved default link target URL. The Location header contains the target URL. When fwqs is enabled on the matched link variant, query parameters from the resolution request (e.g. decryptionKey) are appended to the target URL."
          },
          "400": {
            "description": "Identifier path does not match registered scheme patterns. The namespace is not registered, the identifierKeyType is not a valid application identifier within the namespace, or the identifierKey does not match the registered regex pattern.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldErrorsResponse"
                }
              }
            }
          },
          "404": {
            "description": "No link resolver entry found for this identifier. The namespace + identifierKeyType + identifierKey + qualifierPath combination has no registered links, or the entry exists but is inactive."
          }
        },
        "tags": [
          "Link Resolution"
        ]
      }
    },
    "/.well-known/resolver": {
      "get": {
        "operationId": "CommonController_getResolver",
        "summary": "Resolver Description File",
        "description": "Returns the Resolver Description File per ISO/IEC 18975 section 7 and IETF RFC 8615 (well-known URIs). Declares the resolver's supported identifier namespaces, capabilities, and conformance level. Clients SHOULD check this endpoint before assuming a domain hosts an IDR service. Implements IDR-14 (resolver discovery). This endpoint is public and does not require authentication.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Resolver Description File returned successfully. Contains the resolver's supported namespaces, conformance level, and service metadata per ISO/IEC 18975 section 7."
          }
        },
        "tags": [
          "Link Resolution"
        ]
      }
    },
    "/voc": {
      "get": {
        "operationId": "CommonController_getVoc",
        "summary": "List supported link type vocabularies",
        "description": "Returns the resolver's supported link type vocabulary. When show=linktypes, lists all registered link types with their definitions, titles, and namespace prefixes. The prefix parameter filters by vocabulary namespace — for example, \"untp\" returns only UNTP-defined link types (dpp, dcc, dfr, dte, idr), while \"gs1\" returns GS1-defined types (certificationInfo, hasRetailers, etc.). This endpoint is public and does not require authentication.",
        "parameters": [
          {
            "name": "show",
            "required": false,
            "in": "query",
            "description": "Set to \"linktypes\" to retrieve the full link type vocabulary. When omitted, returns a summary of available vocabulary categories.",
            "schema": {
              "type": "string",
              "example": "linktypes"
            }
          },
          {
            "name": "prefix",
            "required": false,
            "in": "query",
            "description": "Filter link types by vocabulary namespace prefix (e.g. \"untp\" for UNTP-defined types, \"gs1\" for GS1 types). Only applies when show=linktypes. When omitted, all link types across all namespaces are returned.",
            "schema": {
              "type": "string",
              "example": "gs1"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Link type vocabulary returned successfully. When show=linktypes, returns an array of link type definitions with their namespace, shortcode, title, and description."
          }
        },
        "tags": [
          "Link Resolution"
        ]
      }
    },
    "/voc/{linktype}": {
      "get": {
        "operationId": "CommonController_getLinkType",
        "summary": "Get link type details",
        "description": "Returns the detailed definition of a specific link type, including its namespace, title, description, and any associated metadata. Use this to look up the semantics of a link type encountered in a linkset response. This endpoint is public and does not require authentication.",
        "parameters": [
          {
            "name": "linktype",
            "required": true,
            "in": "path",
            "description": "The link type identifier to look up (e.g. \"gs1:certificationInfo\", \"untp:dpp\"). Must match a link type registered in the resolver's vocabulary.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Link type definition returned successfully."
          },
          "404": {
            "description": "The specified link type is not registered in this resolver's vocabulary."
          }
        },
        "tags": [
          "Link Resolution"
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "type": "http",
        "description": "JWT bearer token for authenticated management operations (link registration, link management, identifier scheme management). Resolution endpoints (link resolution, /.well-known/resolver, vocabulary) are public and do not require authentication. Token issuance and claims are implementation-specific — the resolver operator defines the authentication provider and authorization model."
      }
    },
    "schemas": {
      "ApplicationIdentifier": {
        "type": "object",
        "description": "Defines a single identifier type within an identifier scheme. Application identifiers can be primary identifiers (type \"I\") that form the main resolution key, optional scheme-defined path continuations historically called qualifiers (type \"Q\"), or data attributes (type \"D\"). Type \"Q\" entries are optional and scheme-specific — many non-GS1 schemes register only type \"I\".",
        "properties": {
          "title": {
            "type": "string",
            "description": "Human-readable name for this identifier type (e.g. \"Global Trade Item Number (GTIN)\", \"Batch or Lot Number\"). Displayed in management interfaces and documentation.",
            "example": "Opaque product identifier"
          },
          "label": {
            "type": "string",
            "description": "Short display label for compact UI rendering (e.g. \"GTIN\", \"BATCH/LOT\", \"NLISID\"). Typically an abbreviation or acronym.",
            "example": "PRODUCT"
          },
          "shortcode": {
            "type": "string",
            "description": "URL-friendly identifier used in resolution paths (e.g. \"product\", \"25S\", \"gtin\", \"nlisid\"). For GS1 schemes, the shortcode may map to a human-readable form of an Application Identifier. This value appears in the identifierKeyType segment of the resolution URL path. Not required to be a GS1 AI.",
            "example": "product"
          },
          "ai": {
            "type": "string",
            "description": "Optional scheme code corresponding to ISO/IEC 15418 Application Identifier or Data Identifier encoding (e.g. \"01\" for GS1 GTIN, \"25S\" for an ASC MH10 DI). Omit for opaque register schemes that do not use 15418 codes. Defaults to the shortcode value if omitted.",
            "example": "product"
          },
          "type": {
            "type": "string",
            "description": "Classification of this application identifier. \"I\" = primary Identifier (forms the main resolution key), \"Q\" = optional scheme-defined path continuation (e.g. GS1 batch/serial), \"D\" = Data attribute (does not participate in resolution path construction). Only \"I\" is required for a usable scheme.",
            "example": "I",
            "enum": [
              "I",
              "Q",
              "D"
            ]
          },
          "regex": {
            "type": "string",
            "description": "Regular expression validation pattern for the identifier value. Resolution rejects identifiers that do not match this pattern with a 400 error. Patterns should be anchored and specific to prevent false matches (e.g. \"(\\\\d{12,14}|\\\\d{8})\" for GTIN).",
            "example": "[A-Za-z0-9_-]{1,64}"
          },
          "format": {
            "type": "string",
            "description": "Human-readable format descriptor (e.g. \"N14\" for 14 numeric digits, \"X..20\" for up to 20 alphanumeric characters). Informational only — validation is performed using the regex field.",
            "example": "X..20"
          },
          "qualifiers": {
            "description": "Optional list of type-\"Q\" codes that may appear after this primary identifier in the resolution path. Only applicable when type is \"I\". Leave empty or omit for schemes that use a single opaque identifier. For GS1, a GTIN might list [\"10\", \"21\"] for batch/serial — that is scheme configuration, not a UNTP mandate.",
            "example": [],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "title",
          "label",
          "shortcode",
          "type",
          "regex"
        ]
      },
      "IdentifierDto": {
        "type": "object",
        "description": "Configuration for an identifier scheme (namespace). Defines the set of identifier types that may be resolved under this namespace and their validation rules. Must be registered before any link registration can reference this namespace. Namespaces may represent GS1, ISO/IEC 15459 / ASC MH10, national registers, or other EN 18219-aligned schemes.",
        "properties": {
          "namespace": {
            "type": "string",
            "description": "Unique name for the identifier scheme (e.g. \"gs1\", \"nlis\", \"integrity-systems\"). Must match the scheme's registration in the UNTP IDR register. This value appears as the first path segment in resolution URLs.",
            "example": "products.sample-register.example"
          },
          "namespaceURI": {
            "type": "string",
            "description": "Optional URI providing an authoritative reference for the identifier scheme (e.g. the scheme owner's domain or specification URL). Informational — used for documentation and provenance, not for resolution.",
            "example": ""
          },
          "namespaceProfile": {
            "type": "string",
            "description": "Optional profile identifier for scheme-specific resolver configuration. Allows a single namespace to support multiple resolution profiles (e.g. different validation rules or link type vocabularies for different use cases).",
            "example": ""
          },
          "applicationIdentifiers": {
            "description": "The set of identifier types supported within this scheme. Must include at least one primary identifier (type \"I\"). Optional type \"Q\" path continuations and type \"D\" data attributes are scheme-specific and not required.",
            "example": [
              {
                "title": "Opaque product identifier",
                "label": "PRODUCT",
                "shortcode": "product",
                "type": "I",
                "regex": "[A-Za-z0-9_-]{1,64}"
              }
            ],
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApplicationIdentifier"
            }
          }
        },
        "required": [
          "namespace",
          "applicationIdentifiers"
        ]
      },
      "Response": {
        "type": "object",
        "description": "A single link variant within a resolver entry. Each response represents one combination of link type, language, MIME type, geographic context, and access role — per UNTP IDR-06 (one carrier, many links). Multiple responses on the same identifier allow different stakeholders to discover different credentials in different formats and languages.",
        "properties": {
          "linkId": {
            "type": "string",
            "description": "Server-generated unique identifier for this link variant (UUID format). Read-only — assigned on creation and used for subsequent GET, PUT, and DELETE operations on this specific link.",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "readOnly": true
          },
          "linkType": {
            "type": "string",
            "description": "IANA or scheme-specific link relation type. UNTP defines: \"untp:dpp\" (Digital Product Passport), \"untp:dcc\" (Digital Conformity Credential), \"untp:dfr\" (Digital Facility Record), \"untp:dte\" (Digital Traceability Event), \"untp:idr\" (Identity Resolver). Scheme-specific types use the {namespace}:{type} convention (e.g. \"gs1:certificationInfo\"). Implements IDR-07.",
            "example": "example-identifier-scheme:certificationInfo"
          },
          "rel": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Additional IANA or extension link relation types that qualify this link beyond its primary linkType — for example \"edit\" or \"latest-version\". Optional. Note: \"predecessor-version\" is reserved — the resolver derives it automatically from version history when a link variant is replaced and SHOULD NOT be set explicitly by publishers.",
            "example": [
              "edit"
            ]
          },
          "title": {
            "type": "string",
            "description": "Human-readable title for this link variant, displayed in linkset responses and management interfaces (e.g. \"Certification Information\", \"Digital Product Passport (English)\").",
            "example": "Certification Information"
          },
          "targetUrl": {
            "type": "string",
            "description": "The URL that resolution redirects to or includes in the linkset. For UNTP credentials, this is typically the URL where the Verifiable Credential can be retrieved. When fwqs is enabled, query parameters from the resolution request are appended to this URL.",
            "example": "https://example.com"
          },
          "mimeType": {
            "type": "string",
            "pattern": "\\w+/[-+.\\w]+",
            "description": "Media type of the target resource — any well-formed MIME type per RFC 6838 is accepted. For UNTP verifiable credentials, use \"application/vc+ld+json\" (W3C VC 2.0). Other common values: \"application/json\", \"application/pdf\" for human-readable documents, \"application/linkset+json\" for embedded linksets. Implements content negotiation per IDR-08.",
            "example": "application/json"
          },
          "hreflang": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "(^\\w{2}$)|(^\\w{2}-\\w{2}$)"
            },
            "description": "BCP 47 language tags supported by the resource at the target URL. Content negotiation is handled at the target — a single targetUrl may return, for example, English, French, or German variants of the same resource based on the request's Accept-Language header, in which case hreflang would be [\"en\", \"fr\", \"de\"]. Consumers use this list to know which languages they can request from the target before issuing the call. Implements IDR-08 language negotiation.",
            "example": [
              "en"
            ]
          },
          "context": {
            "type": "string",
            "description": "Geographic or situational context code (e.g. \"au\" for Australia, \"eu\" for European Union, \"us\" for United States). Implements IDR-08 context negotiation — allows different link targets for different jurisdictions. For example, a product may have different conformity credentials for different regulatory contexts.",
            "example": "au"
          },
          "defaultLinkType": {
            "type": "boolean",
            "description": "When true, this variant is the default for its link type dimension. Resolution returns this variant when no linkType filter is specified in the request. Exactly one response per identifier SHOULD be marked as the default link type.",
            "example": true
          },
          "defaultMimeType": {
            "type": "boolean",
            "description": "When true, this variant is the default for its MIME type dimension. Resolution returns this variant when multiple MIME types are available and no preference is specified.",
            "example": true
          },
          "defaultContext": {
            "type": "boolean",
            "description": "When true, this variant is the default for its context dimension. Resolution returns this variant when no geographic/situational context is specified.",
            "example": true
          },
          "fwqs": {
            "type": "boolean",
            "description": "Forward Query String. When true, query parameters from the resolution request (e.g. decryptionKey) are appended to the targetUrl on redirect. Essential for encrypted credential retrieval per IDR-10 — the decryption key is passed through to the credential host without being stored by the resolver.",
            "example": false
          },
          "active": {
            "type": "boolean",
            "description": "Whether this link variant is live and included in resolution responses. Inactive links are excluded from resolution but retained in storage. Set to false for soft-delete or to temporarily disable a link variant.",
            "example": true
          },
          "encryptionMethod": {
            "type": "string",
            "description": "Encryption algorithm applied to the target resource. \"none\" indicates the target is unencrypted (public access). \"AES-128\" or \"AES-256\" indicate the credential at the target URL is encrypted and requires a decryptionKey to access. Implements IDR-10 secure targets for confidential credentials.",
            "enum": [
              "none",
              "AES-128",
              "AES-256"
            ],
            "example": "none"
          },
          "accessRole": {
            "type": "array",
            "description": "UNTP access roles permitted to retrieve this link variant. Implements variant-based disclosure filtering per IDR-10. During resolution, only variants whose accessRole array includes the requested role (or \"untp:accessRole#Anonymous\" for unauthenticated requests) are returned. Multiple roles can be assigned to a single variant.",
            "example": [
              "untp:accessRole#Anonymous"
            ],
            "items": {
              "type": "string",
              "enum": [
                "untp:accessRole#Anonymous",
                "untp:accessRole#Customer",
                "untp:accessRole#Regulator",
                "untp:accessRole#Recycler",
                "untp:accessRole#Auditor",
                "untp:accessRole#Owner"
              ]
            }
          },
          "public": {
            "type": "boolean",
            "description": "Whether the link itself is safe to share publicly (e.g. publish in directories, broadcast on product packaging). Distinct from accessRole, which controls who can retrieve the resource at the URL — a link with public: true and accessRole: [\"untp:accessRole#Customer\"] is safe to advertise, but only customers can retrieve the underlying resource. Optional; if omitted, publishers SHOULD assume the link is not safe to share.",
            "example": true
          },
          "method": {
            "type": "string",
            "description": "HTTP method for accessing the target resource. \"GET\" for retrieval of existing credentials. \"POST\" for creating new linked resources (e.g. submitting traceability events or conformity credentials back to the identifier owner). Implements IDR-10 edit links, enabling bidirectional data flows in supply chains.",
            "example": "POST"
          }
        },
        "required": [
          "defaultLinkType",
          "defaultMimeType",
          "fwqs",
          "active",
          "linkType",
          "title",
          "targetUrl",
          "mimeType",
          "hreflang",
          "context",
          "defaultContext"
        ]
      },
      "CreateLinkRegistrationDto": {
        "type": "object",
        "description": "Registers a link resolver entry per IDR-02 (one carrier, many links). Associates a specific identifier — defined by namespace, identificationKeyType, identificationKey, and optional qualifierPath — with one or more typed link targets. Each entry in the responses array represents a link variant that can be discovered through resolution.",
        "properties": {
          "namespace": {
            "type": "string",
            "description": "Must reference a previously registered identifier scheme (see POST /identifiers). The namespace identifies which scheme this identifier belongs to (e.g. \"gs1\", \"nlis\").",
            "example": "example-identifier-scheme"
          },
          "identificationKeyType": {
            "type": "string",
            "description": "Must be a registered shortcode within the specified namespace (e.g. \"product\" for an opaque register, \"25S\" for ASC MH10, \"gtin\" for GS1). Determines which application identifier type this entry is for. Not limited to GS1.",
            "example": "product"
          },
          "identificationKey": {
            "type": "string",
            "description": "The specific identifier value being registered (e.g. \"ABC123456\", \"IAC42PROD987654\", or a GTIN). Must match the regex pattern configured for the identificationKeyType in the namespace's scheme definition.",
            "example": "ABC123456"
          },
          "description": {
            "type": "string",
            "description": "Human-readable description of the identified item (e.g. \"Recycled Copper Cathode — 99.99% purity\"). Included in linkset responses to help consumers understand what the identifier refers to.",
            "example": "Product description"
          },
          "itemDescription": {
            "type": "string",
            "description": "Deprecated: Use \"description\" instead. If both are provided, \"description\" takes precedence.",
            "example": "Product description",
            "deprecated": true
          },
          "qualifierPath": {
            "type": "string",
            "description": "Optional scheme-specific path continuation after the primary identifier (e.g. \"/21/SER456\" for a GS1 serial). Use \"/\" or empty for opaque identifiers with no extra segments. Not required for non-GS1 schemes that encode full identity in identificationKey.",
            "example": "/10/12345678901234567890"
          },
          "active": {
            "type": "boolean",
            "description": "Whether this resolver entry is live. When false, the identifier returns 404 on resolution even if link variants exist. Useful for pre-registering links before they should be publicly discoverable.",
            "example": true
          },
          "responses": {
            "description": "Array of link targets (variants). Each entry represents one link variant per IDR-06 — a unique combination of link type, language, MIME type, geographic context, and access role. For a typical UNTP product, this might include a DPP credential (JSON), a conformity certificate (PDF), and a human-readable product page (HTML), each potentially in multiple languages.",
            "example": [
              {
                "defaultLinkType": true,
                "defaultMimeType": true,
                "defaultContext": true,
                "fwqs": false,
                "active": true,
                "linkType": "example-identifier-scheme:certificationInfo",
                "rel": [
                  "edit"
                ],
                "hreflang": [
                  "en"
                ],
                "context": "au",
                "title": "Certification Information",
                "targetUrl": "https://example.com",
                "mimeType": "application/json",
                "encryptionMethod": "none",
                "accessRole": [
                  "untp:accessRole#Anonymous"
                ],
                "public": true,
                "method": "POST"
              }
            ],
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Response"
            }
          }
        },
        "required": [
          "namespace",
          "identificationKeyType",
          "identificationKey",
          "description",
          "qualifierPath",
          "active",
          "responses"
        ]
      },
      "FieldError": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "example": "identificationKeyType"
          },
          "message": {
            "type": "string",
            "example": "Identification key type 'invalid_key_type' is not registered with the namespace 'example-identifier-scheme'"
          }
        },
        "required": [
          "field",
          "message"
        ]
      },
      "FieldErrorsResponse": {
        "type": "object",
        "properties": {
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FieldError"
            }
          }
        },
        "required": [
          "errors"
        ]
      },
      "UpdateLinkDto": {
        "type": "object",
        "description": "Partial update for a single link variant. All fields are optional — only the fields included in the request body are modified. Omitted fields retain their current values. Use this to rotate target URLs, update access roles, toggle active status, or change encryption methods without affecting other properties.",
        "properties": {
          "targetUrl": {
            "type": "string",
            "description": "The URL that resolution redirects to or includes in the linkset. Update this to rotate credential hosting URLs or point to a new version of the target resource.",
            "example": "https://example.com"
          },
          "linkType": {
            "type": "string",
            "description": "IANA or scheme-specific link relation type (e.g. \"untp:dpp\", \"gs1:certificationInfo\"). Changing the link type changes how this variant is classified in resolution and linkset responses.",
            "example": "example-identifier-scheme:certificationInfo"
          },
          "rel": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Additional IANA or extension link relation types that qualify this link beyond its primary linkType. Replaces the existing rel array (does not merge). \"predecessor-version\" is reserved — see Response schema.",
            "example": [
              "edit"
            ]
          },
          "title": {
            "type": "string",
            "description": "Human-readable title for this link variant.",
            "example": "Certification Information"
          },
          "mimeType": {
            "type": "string",
            "pattern": "\\w+/[-+.\\w]+",
            "description": "Media type of the target resource — any well-formed MIME type per RFC 6838 is accepted (e.g. \"application/vc+ld+json\", \"application/json\", \"application/pdf\", \"application/linkset+json\").",
            "example": "application/json"
          },
          "hreflang": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "(^\\w{2}$)|(^\\w{2}-\\w{2}$)"
            },
            "description": "BCP 47 language tags supported by the resource at the target URL — content negotiation is handled at the target.",
            "example": [
              "en"
            ]
          },
          "context": {
            "type": "string",
            "description": "Geographic or situational context code (e.g. \"au\", \"eu\", \"us\").",
            "example": "au"
          },
          "active": {
            "type": "boolean",
            "description": "Whether this link variant is live and included in resolution responses. Set to false to deactivate without deleting."
          },
          "fwqs": {
            "type": "boolean",
            "description": "Forward Query String. When true, query parameters from the resolution request are appended to the targetUrl on redirect."
          },
          "defaultLinkType": {
            "type": "boolean",
            "description": "When true, this variant is the default for its link type dimension."
          },
          "defaultContext": {
            "type": "boolean",
            "description": "When true, this variant is the default for its context dimension."
          },
          "defaultMimeType": {
            "type": "boolean",
            "description": "When true, this variant is the default for its MIME type dimension."
          },
          "encryptionMethod": {
            "type": "string",
            "description": "Encryption algorithm applied to the target resource. \"none\" for unencrypted, \"AES-128\" or \"AES-256\" for encrypted credentials requiring a decryptionKey.",
            "enum": [
              "none",
              "AES-128",
              "AES-256"
            ],
            "example": "none"
          },
          "accessRole": {
            "type": "array",
            "description": "UNTP access roles permitted to retrieve this link variant. Updates the full role list (replaces, does not merge).",
            "example": [
              "untp:accessRole#Anonymous"
            ],
            "items": {
              "type": "string",
              "enum": [
                "untp:accessRole#Anonymous",
                "untp:accessRole#Customer",
                "untp:accessRole#Regulator",
                "untp:accessRole#Recycler",
                "untp:accessRole#Auditor",
                "untp:accessRole#Owner"
              ]
            }
          },
          "public": {
            "type": "boolean",
            "description": "Whether the link itself is safe to share publicly. Distinct from accessRole — see Response schema for full semantics."
          },
          "method": {
            "type": "string",
            "description": "HTTP method for accessing the target. \"GET\" for retrieval, \"POST\" for creating new linked resources.",
            "example": "POST"
          }
        }
      }
    }
  }
}
