---
title: "DID Web Registry Setup Guide"
description: "This guide walks through a complete end-to-end setup: tenant, supporting services, DID Registry, custom domain via a host alias, and creating a resolvable did:web."
stack: "Enterprise Stack (commercial) — version 1.1.1"
stack_version: "1.1.1"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/enterprise-stack/services/did-registry/did-web-registry-setup-guide
generated: 2026-10-01
---
# DID Web Registry Setup Guide

This guide walks through a complete end-to-end setup: tenant, supporting services, DID Registry, custom domain via a host alias, and creating a resolvable `did:web`.

It assumes you use the **Enterprise API Gateway** — an optional component that exposes public resolution endpoints while keeping the main Enterprise API private. Custom domains typically point to the Gateway rather than the internal API.

**Note:**

Replace placeholder values throughout this guide:
- `waltid` — your organization ID
- `did-registry-tenant` — your tenant name
- `enterprise.test.waltid.cloud` — your Enterprise API domain
- `registry.test.waltid.cloud` — your custom resolution domain

## Architecture

```mermaid
flowchart LR
    Client[Resolver / Wallet] -->|HTTPS| Gateway[Enterprise API Gateway]
    Gateway -->|did.json requests| Registry[DID Registry Service]
    Registry --> Store[DID Store Service]
    DID[DID Service] --> Store
    DID --> KMS[KMS Service]
```

## Step 1: Create the tenant

Create a tenant and pre-configure which DID Registry service it will use. The registry service ID (`did-web-registry`) must match the service you create in Step 5.

```bash
curl -w "
HTTP %{http_code}
" -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/did-registry-tenant/resource-api/tenants/create' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "DID Registry Example Tenant",
    "configuration": {
       "didRegistry": "waltid.did-registry-tenant.did-web-registry"
    }
  }'
```

Expected: `201`

## Step 2: Create the DID Store

The DID Store persists DID documents. Both the DID Service and DID Registry depend on it.

```bash
curl -w "
HTTP %{http_code}
" -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/did-registry-tenant.did-store/resource-api/services/create' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "did-store"
}'
```

Expected: `201`

## Step 3: Create the DID Service

The DID Service creates `did:web` identifiers and stores documents in the DID Store.

```bash
curl -w "
HTTP %{http_code}
" -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/did-registry-tenant.did-service/resource-api/services/create' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "did"
}'
```

Expected: `201`

Wire the DID Service to the DID Store:

```bash
curl -w "
HTTP %{http_code}
" -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/did-registry-tenant.did-service/did-service-api/dids/dependencies/add' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "dependency": "waltid.did-registry-tenant.did-store"
}'
```

Expected: `201`

## Step 4: Create the DID Registry Service

```bash
curl -w "
HTTP %{http_code}
" -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/did-registry-tenant.did-web-registry/resource-api/services/create' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "did-registry"
}'
```

Expected: `201`

Wire the DID Registry to the DID Store:

```bash
curl -w "
HTTP %{http_code}
" -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/did-registry-tenant.did-web-registry/did-registry-service-api/dependencies/add' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "dependency": "waltid.did-registry-tenant.did-store"
}'
```

Expected: `201`

## Step 5: Create a host alias

Map a custom domain to the tenant so DIDs can use `registry.test.waltid.cloud` instead of the default Enterprise domain.

```bash
curl -w "
HTTP %{http_code}
" -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/waltid.registry-host-alias/host-alias-api/host-aliases/create' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "domain": "registry.test.waltid.cloud"
}'
```

Expected: `201`

## Step 6: Create a KMS and key

DIDs need a signing key from KMS.

```bash
# Create KMS
curl -w "
HTTP %{http_code}
" -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/did-registry-tenant.kms/resource-api/services/create' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -d '{
  "type": "kms"
}'

# Generate a key — save the returned keyId for the next step
curl -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/did-registry-tenant.kms/kms-service-api/keys/generate' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -d '{
  "backend": "jwk",
  "keyType": "secp256r1"
}'
```

Wire the DID Service to the KMS — without this, DID creation in the next step fails with `400 No dependency for KMS with resource path '...'`:

```bash
curl -w "
HTTP %{http_code}
" -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/did-registry-tenant.did-service/did-service-api/dids/dependencies/add' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "dependency": "waltid.did-registry-tenant.kms"
}'
```

Expected: `201`

## Step 7: Create a did:web

Create the DID using the custom domain and a tenant-scoped path. Replace `{keyId}` with the key ID from Step 6.

```bash
curl -w "
HTTP %{http_code}
" -X 'POST' \
  'https://waltid.enterprise.test.waltid.cloud/v1/did-registry-tenant.did-service/did-service-api/dids/create/web' \
  -H 'Authorization: Bearer {yourBearerToken}' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "single_key_reference",
  "keyReference": "{keyId}",
  "domain": "registry.test.waltid.cloud",
  "path": "did-registry-tenant/max"
}'
```

Expected: `201` with a response containing `"did": "did:web:registry.test.waltid.cloud:did-registry-tenant:max"`.

## Step 8: Verify resolution

The created DID is routed as follows:

| Route | URL | Notes |
|:------|:----|:------|
| **Public resolution** (use this) | `https://registry.test.waltid.cloud/did-registry-tenant/max/did.json` | Standard `did:web` HTTPS resolution |
| Gateway (colon-encoded) | `https://registry.test.waltid.cloud/did-registry-tenant:max:did.json` | Non-standard; do not use |
| Internal API | `https://waltid.enterprise.test.waltid.cloud/v1/waltid.did-registry-tenant.did-web-registry/did-registry-service-api/registry/did-registry-tenant:max/did.json` | Internal only — `{id}` is the colon-separated path suffix only, without the domain |

Verify the public URL:

```bash
curl https://registry.test.waltid.cloud/did-registry-tenant/max/did.json
```

A `200` response with the DID document JSON confirms the full setup is working.

## Troubleshooting

| Symptom | Check |
|:--------|:------|
| `404` on resolution URL | DID Store dependency on both DID Service and DID Registry; `domain` and `path` match the URL |
| Wrong domain in DID | Host alias created; `domain` parameter uses the custom domain, not the Enterprise API domain |
| Tenant config mismatch | `didRegistry` in tenant config matches the full registry service ID |
| Gateway not routing | DNS points to Gateway; Gateway configured to forward `did.json` requests |

See also [External DID Web Hosting](https://docs.walt.id/enterprise-stack/services/did-registry/external-did-web-hosting.md) for DNS and reverse-proxy configuration.
