Skip to main content
Version: Next

DIDs API

The DIDs API manages Decentralised Identifiers (DIDs) — the cryptographic identities that the Reference Implementation uses to sign verifiable credentials. Every credential issued by the Reference Implementation is signed with a DID — either one the tenant has provisioned or the system default DID available to all tenants.

For background on how DIDs relate to the verifiable credential service, see Verifiable Credential Service.

Interactive API documentation

The Reference Implementation includes a Swagger UI at /api-docs with full request/response schemas you can try directly from the browser. The endpoint descriptions below focus on behaviour and internal logic — refer to Swagger for exact payload shapes. All endpoints require authentication — see Authentication for how to obtain a Bearer token.

Concepts

DID Types

Every DID has a type that determines how it was created, who manages its key material, and who hosts its DID document. The types represent an adoption ramp — tenants can issue UNTP-compliant credentials from day one using the system default, and progressively take on more control as they become more technically sophisticated.

DEFAULT

A system DID created during startup. It belongs to the system tenant and is available to all tenants as a read-only default. The DID document and key material are hosted by the system's verifiable credential service. Default DIDs cannot be deleted or verified through the API. Initial status: ACTIVE.

MANAGED

The DID was created by the verifiable credential service via POST /api/v1/dids. The VC service holds the cryptographic key material (public and private key), hosts the DID document, and performs all signing operations. The Reference Implementation stores a record of the DID, its status, and which service instance manages it. Initial status: ACTIVE.

This is the simplest path for tenants that want their own DID — they create one and the VC service handles everything. The alias is a short identifier that the VC service prefixes with its own endpoint to form the full DID (e.g., alias my-company might produce did:web:vckit.example.com:my-company).

SELF_MANAGED

A self-managed DID gives the tenant more control. There are two paths:

  1. Create via the API (POST /api/v1/dids) — The Reference Implementation calls the VC service to create the DID, so the VC service still holds the cryptographic key material and performs signing. However, the tenant is responsible for hosting the DID document at the location the DID identifier resolves to. The alias should be the full domain or path where the tenant will host the DID document (e.g., example.com for did:web:example.com). Initial status: UNVERIFIED.

  2. Import an existing DID (POST /api/v1/dids/import) — The tenant has provisioned their own verifiable credential service instance (registered via the Services API), which already has a DID created in it. The tenant imports that DID into the Reference Implementation for tracking. The key material and DID document live entirely within the tenant's own infrastructure. The tenant must have added their VC service instance to their tenant before importing. When importing, the full DID identifier is provided via the did field (e.g., did:web:example.com). Initial status: UNVERIFIED.

In both cases, self-managed DIDs start as UNVERIFIED and should be confirmed via the verify endpoint.

Hosting the DID Document (did:web)

For self-managed DIDs using the did:web method, the tenant must host the DID Document at the URL that the DID identifier resolves to. The hosting location depends on the structure of the identifier:

DID IdentifierHosted At
did:web:example.comhttps://example.com/.well-known/did.json
did:web:example.com:departmenthttps://example.com/department/did.json
did:web:example.com:org:unithttps://example.com/org/unit/did.json

The rule follows the did:web specification: colons after the domain are converted to path separators, and did.json is appended. When only the domain is used (no additional path segments), the document must be placed at /.well-known/did.json.

The DID document must be served over HTTPS with a valid TLS certificate.

When creating a self-managed DID via the API, the alias value determines the resulting DID identifier — set it to the domain (e.g., example.com) or domain with path (e.g., example.com:department) where you will host the document.

DID Methods

The method field identifies which DID method the identifier conforms to. The supported methods are aligned with the UNTP Verifiable Credential profile.

MethodStatusDescription
DID_WEBSupporteddid:web — a DID method that uses web domains as the basis for the identifier
DID_WEB_VHPlannedA variant of did:web with version history support — not yet implemented

DID Statuses

StatusDescription
ACTIVEThe DID is ready to use for credential signing
UNVERIFIEDThe DID has been registered but it has not yet been confirmed that the DID document can be resolved
VERIFIEDThe DID document has been successfully resolved via the verify endpoint
VERIFICATION_FAILEDThe verification check failed — the DID document could not be resolved
INACTIVEReserved for future use — deactivation of DIDs is not yet implemented

Verification Checks

The verify endpoint runs the following checks in order. All checks must pass for the DID to be marked as VERIFIED.

CheckDescription
ResolveFetches the DID document from the URL the DID identifier resolves to (e.g., https://example.com/.well-known/did.json for did:web:example.com). Fails if the document cannot be retrieved or returns a non-success HTTP status.
HTTPSConfirms the DID document was served over HTTPS. Checks the final URL after any redirects — if a redirect lands on an insecure connection, this check fails.
StructureValidates the retrieved DID document against the DID Document schema. Fails if required fields are missing or malformed.
Identity matchConfirms that the id field in the DID document matches the DID identifier. Fails if they differ (e.g., the document was served from the wrong location).
Key materialFetches the key IDs from the VC service instance associated with the DID and confirms they correspond to the key IDs listed in the DID document's verificationMethod entries. This ensures the DID document points to the same keys that the VC service actually holds for signing. Fails if none of the VC service's keys appear in the document.
JSON-LD validityValidates that the DID document is valid JSON-LD. Currently skipped — disabled to avoid SSRF risks from untrusted @context URLs in DID documents.

System DIDs vs Tenant DIDs

DIDs exist at two levels — the system default DID (created during startup, owned by the system tenant, read-only and visible to all tenants) and tenant DIDs (created or imported by a tenant through this API, scoped exclusively to that tenant). When listing DIDs, tenants see both their own DIDs and the system default.

Service Instance Association

When creating a DID, you can specify which verifiable credential service instance to use via serviceInstanceId. If omitted, the service instance is resolved using the same resolution chain as other operations — the tenant's primary VC service instance if one is set, otherwise the system default.

The service instance is the upstream provider that holds the cryptographic key material and performs signing operations.

Default DID

Each tenant can designate one DID as its default (isDefault: true). The default DID is used when other operations (such as credential issuance) need a signing identity but none is explicitly specified.

Endpoints

Create a DID

POST /api/v1/dids

Calls the verifiable credential service to create a new DID, then stores a record of it in the Reference Implementation.

For managed DIDs, the VC service generates a new key pair, creates the DID, and hosts the DID document. The Reference Implementation stores a record linking the DID to the tenant and service instance. The DID is immediately ACTIVE and ready for credential signing.

For self-managed DIDs created via this endpoint, the VC service still generates the key pair and creates the DID — the difference is that the tenant is responsible for hosting the DID document at the location the DID identifier resolves to (see Self-Managed DID type for details). The DID starts as UNVERIFIED and should be confirmed via the verify endpoint once the DID document is hosted.


List DIDs

GET /api/v1/dids

Returns DIDs for the authenticated tenant with optional filtering. Results are paginated.


Get a DID

GET /api/v1/dids/{id}

Retrieves a specific DID by its database ID.


Update a DID

PATCH /api/v1/dids/{id}

Updates the metadata of a DID. Only name, description, and isDefault can be changed — the DID identifier, type, method, and key material are immutable.


Delete a DID

DELETE /api/v1/dids/{id}

Deletes a DID from the Reference Implementation database. If the DID still has an associated service instance (the association can be lost if the service instance was force-deleted), the Reference Implementation also attempts to remove the DID from the upstream VC service on a best-effort basis — if the upstream deletion fails, the local record is still deleted and a warning is logged.

DIDs marked as isDefault cannot be deleted. Remove the default flag first via the update endpoint, then delete.


Get DID Document

GET /api/v1/dids/{id}/document

Retrieves the DID Document for a specific DID from the upstream verifiable credential service. The DID Document contains the public keys, authentication methods, and service endpoints associated with the DID — it is the publicly resolvable representation of the DID.

The VC service resolves the DID by fetching the DID document from wherever it is hosted. For managed DIDs, the VC service itself is the host. For self-managed DIDs, this is the location where the tenant has published their DID document.


Verify a DID

POST /api/v1/dids/{id}/verify

Verifies that a DID can be resolved and that its DID document is valid. The DID's status is updated based on the result — VERIFIED if all checks pass, VERIFICATION_FAILED otherwise.

This endpoint is used for self-managed DIDs — both those created via the API and those imported — which start with status UNVERIFIED. It confirms that the DID document is publicly resolvable and structurally valid.

System default DIDs (type: DEFAULT) cannot be verified through this endpoint. See Verification Checks for the full list of checks performed.


Import a DID

POST /api/v1/dids/import

Registers an existing, externally managed DID in the Reference Implementation without calling the upstream VC service's create method. The DID is stored as SELF_MANAGED with status UNVERIFIED.

Use this endpoint when you have a DID that was created outside the Reference Implementation (e.g., in a separate verifiable credential service instance) and you want to use it for credential signing within the Reference Implementation. After importing, use the verify endpoint to confirm that the DID document is resolvable.

Before importing, the tenant must have registered the verifiable credential service instance that holds the DID via the Services API. The serviceInstanceId is required — this is how the Reference Implementation knows which VC service to use when signing credentials with this DID.

Note that unlike the create endpoint, the import endpoint does not call the upstream VC service. It only creates a local database record.