Resolution

The DID Registry exposes unauthenticated GET endpoints that serve DID documents as did.json. All patterns fan out to every DID Store linked as a dependency on the registry.

The registry does not host documents at the standard did:web HTTPS path automatically. To make https://{domain}/{path}/did.json work externally, point your reverse proxy or DNS at these Enterprise API endpoints. See External DID Web Hosting.

Deriving {id} from a DID

For did:web:waltid.enterprise.localhost:users:alice, the {id} path parameter is the colon-separated path suffix: users:alice.

Colons in {id} do not need to be percent-encoded — the server accepts them literally in the path (users:alice). Percent-encoding them (users%3Aalice) also works, if you prefer to encode on principle.

Service-targeted resolution

Resolves {id} against a specific DID Registry instance.

GET /v1/{registry-target}/did-registry-service-api/registry/{id}/did.json
CURL
curl -X GET \
  'https://{orgId}.enterprise.localhost/v1/waltid.tenant1.did-registry-main/did-registry-service-api/registry/users:alice/did.json'

Path Parameters

  • {registry-target} — Full path of the DID Registry service, e.g. waltid.tenant1.did-registry-main
  • {id} — Colon-separated path suffix from the did:web

Response 200 OK

{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:web:waltid.enterprise.localhost:users:alice",
  "verificationMethod": [ ],
  "authentication": [ ]
}

Response 404 Not Found — No DID matching {id} in any linked store:

{
  "message": "No DID found with id: users:alice"
}

Tenant-relative resolution

Resolves against a registry within an organization, without repeating the org ID in the path. The organization itself is resolved from the request's Host header ({orgId}).

GET /{target}/{id}/did.json

{target} names a node in the organization tree, resolved relative to the org root — what kind of node it is determines how the request resolves:

  • DID Registry service (e.g. tenant1.did-registry-main, or the full absolute path waltid.tenant1.did-registry-main) — {id} is resolved against it directly.
  • Tenant (e.g. tenant1) — the tenant's configured didRegistry (see Tenant-level DIDs) is used instead. The stored value is tried both as given and expanded relative to the tenant, so it resolves whether didRegistry was configured as a full absolute path or as a short, tenant-relative service ID.

Both forms fan out to the same DID Stores and produce identical documents — which one you use just depends on whether you'd rather address the registry service directly or via its owning tenant.

If {target} doesn't match any node, or matches a tenant with no didRegistry configured, the request 404s (see Responses below).

CURL
# Target = registry service path
curl -X GET \
  'https://{orgId}.enterprise.localhost/tenant1.did-registry-main/users:alice/did.json'

# Target = tenant ID (registry resolved via the tenant's didRegistry config)
curl -X GET \
  'https://{orgId}.enterprise.localhost/tenant1/users:alice/did.json'

Path Parameters

  • {orgId} — Organization ID, resolved from the request host (e.g. waltid for waltid.enterprise.localhost).
  • {target} — Either a registry service path (relative to the org root, e.g. tenant1.did-registry-main, or absolute, e.g. waltid.tenant1.did-registry-main) or a tenant ID (e.g. tenant1) whose configured didRegistry should be used.
  • {id} — Colon-separated path suffix, e.g. users:alice

Response 404 Not Found{target} doesn't resolve to a registry service or a tenant:

{
  "message": "No DID registry found at: tenant1"
}

Response 404 Not Found{target} is a tenant with no didRegistry configured:

{
  "message": "A DID registry has not been configured for this tenant"
}

Organization root resolution

The simplest form — no service path in the URL. Requires rootDidRegistry to be configured on the organization (see Setup → Step 4).

GET /{id}/did.json
CURL
curl -X GET \
  'https://waltid.enterprise.localhost/users:alice/did.json'

Path Parameters

  • {id} — Colon-separated path suffix

Response 404 Not Found — If rootDidRegistry is not configured:

{
  "message": "A root DID registry has not been installed in this organization"
}

Internally this reads organization.configuration.rootDidRegistry, loads that registry, and resolves {id}.

List registered DIDs

List all did:web identifiers across linked stores:

CURL
curl -X GET \
  'https://{orgId}.enterprise.localhost/v1/waltid.tenant1.did-registry-main/did-registry-service-api/registry/list' \
  -H 'Authorization: Bearer {yourToken}'

Response 200 OK

[
  "did:web:waltid.enterprise.localhost:users:alice",
  "did:web:waltid.enterprise.localhost:org:issuer"
]

Resolution URL summary

PatternExample URL
Service-targeted/v1/waltid.tenant1.did-registry-main/did-registry-service-api/registry/users:alice/did.json
Tenant-relative/tenant1.did-registry-main/users:alice/did.json
Organization root/users:alice/did.json

Next steps

Last updated on August 18, 2026