Setup
Before any did:web work, three services must exist in the organization tree and be wired together: DID Store, DID Service, and DID Registry.
Prerequisites
- An organization (and optionally a tenant) in the Enterprise Stack
- A bearer token with permission to create services and manage dependencies
- A KMS service in the same scope (required by the DID Service for key material)
Step 1: Create a DID Store
The DID Store persists DID entries and their documents. Both the DID Service (write) and DID Registry (read) depend on it.
Endpoint: /v1/{target}/resource-api/services/create | API Reference
Example Request
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-store-main/resource-api/services/create' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"type": "did-store"
}'
Path Parameters
- orgID: String (required) - Your organization ID. Use the organization's Base URL — e.g. if your organization is
waltid, your Base URL iswaltid.enterprise-sandbox.waltid.dev. target: resourceIdentifier (required) – The full path for the service you are about to create:organization.tenant.serviceId. The final segment becomes the stored service ID, so choose it carefully before calling the endpoint.
Header Parameters
- Authorization: String (required) - Bearer token for Enterprise Stack authentication. Format:
Bearer {token}.
Body Parameters
type— Service type. Must be"did-store".
Response 201 Created
{
"type": "did-store",
"_id": "waltid.tenant1.did-store-main"
}
Step 2: Create a DID Service
The DID Service creates DIDs and writes them into linked DID Stores. It requires both a KMS and a DID Store as dependencies.
2a. Create the service
Endpoint: /v1/{target}/resource-api/services/create | API Reference
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-main/resource-api/services/create' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"type": "did"
}'
Path Parameters
- orgID: String (required) - Your organization ID. Use the organization's Base URL — e.g. if your organization is
waltid, your Base URL iswaltid.enterprise-sandbox.waltid.dev. target: resourceIdentifier (required) – The full path for the service you are about to create:organization.tenant.serviceId.
Header Parameters
- Authorization: String (required) - Bearer token for Enterprise Stack authentication. Format:
Bearer {token}.
Body Parameters
type— Service type. Must be"did".
Response 201 Created
{
"type": "did",
"_id": "waltid.tenant1.did-main"
}
2b. Attach KMS dependency
Endpoint: /v1/{target}/did-service-api/dids/dependencies/add | API Reference
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-main/did-service-api/dids/dependencies/add' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"dependency": "waltid.tenant1.kms-main"
}'
Path Parameters
- orgID: String (required) - Your organization ID. Use the organization's Base URL — e.g. if your organization is
waltid, your Base URL iswaltid.enterprise-sandbox.waltid.dev. target: resourceIdentifier (required) – The DID Service instance to attach the dependency to, e.g.waltid.tenant1.did-main.
Header Parameters
- Authorization: String (required) - Bearer token for Enterprise Stack authentication. Format:
Bearer {token}.
Body Parameters
- dependency: String (required) - The dependency's full resource path, e.g.
waltid.tenant1.kms-main.
2c. Attach DID Store dependency
Endpoint: /v1/{target}/did-service-api/dids/dependencies/add | API Reference
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-main/did-service-api/dids/dependencies/add' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"dependency": "waltid.tenant1.did-store-main"
}'
Path Parameters
- orgID: String (required) - Your organization ID. Use the organization's Base URL — e.g. if your organization is
waltid, your Base URL iswaltid.enterprise-sandbox.waltid.dev. target: resourceIdentifier (required) – The DID Service instance to attach the dependency to, e.g.waltid.tenant1.did-main.
Header Parameters
- Authorization: String (required) - Bearer token for Enterprise Stack authentication. Format:
Bearer {token}.
Body Parameters
- dependency: String (required) - The dependency's full resource path, e.g.
waltid.tenant1.did-store-main.
Step 3: Create a DID Registry
The registry fans out resolution queries to all linked DID Stores.
3a. Create the service
Endpoint: /v1/{target}/resource-api/services/create | API Reference
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-registry-main/resource-api/services/create' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"type": "did-registry"
}'
Path Parameters
- orgID: String (required) - Your organization ID. Use the organization's Base URL — e.g. if your organization is
waltid, your Base URL iswaltid.enterprise-sandbox.waltid.dev. target: resourceIdentifier (required) – The full path for the service you are about to create:organization.tenant.serviceId.
Header Parameters
- Authorization: String (required) - Bearer token for Enterprise Stack authentication. Format:
Bearer {token}.
Body Parameters
type— Service type. Must be"did-registry".
Response 201 Created
{
"type": "did-registry",
"_id": "waltid.tenant1.did-registry-main"
}
3b. Attach DID Store dependency
Endpoint: /v1/{target}/did-registry-service-api/dependencies/add | API Reference
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-registry-main/did-registry-service-api/dependencies/add' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"dependency": "waltid.tenant1.did-store-main"
}'
Path Parameters
- orgID: String (required) - Your organization ID. Use the organization's Base URL — e.g. if your organization is
waltid, your Base URL iswaltid.enterprise-sandbox.waltid.dev. target: resourceIdentifier (required) – The DID Registry instance to attach the dependency to, e.g.waltid.tenant1.did-registry-main.
Header Parameters
- Authorization: String (required) - Bearer token for Enterprise Stack authentication. Format:
Bearer {token}.
Body Parameters
- dependency: String (required) - The dependency's full resource path, e.g.
waltid.tenant1.did-store-main.
The DID Store dependency is shared between the DID Service and the DID Registry. When the DID Service creates a did:web, it writes the document into the store. The registry reads it back from the same store at resolution time.
Step 4: Set the root DID Registry (organization level)
For the shortest resolution URL — GET /{id}/did.json with no service path — configure rootDidRegistry on the organization. The organization is resolved from the request's Host header ({orgID}), not from the URL — there is no target path segment on this endpoint:
Endpoint: POST /v1/organization/update-config
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/organization/update-config' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"rootDidRegistry": "waltid.tenant1.did-registry-main"
}'
Path Parameters
- orgID: String (required) - Your organization ID. Use the organization's Base URL — e.g. if your organization is
waltid, your Base URL iswaltid.enterprise-sandbox.waltid.dev. This endpoint always operates on whichever organizationorgIDresolves to; there is no separate target parameter.
Header Parameters
- Authorization: String (required) - Bearer token for Enterprise Stack authentication. Format:
Bearer {token}.
Body Parameters
rootDidRegistry— Full resource path of the registry service. Must be within the organization's namespace.
Response 200 OK (empty body)
This unlocks organization-root resolution at GET /{id}/did.json (on the {orgID} host). Without it, that endpoint returns 404 with "A root DID registry has not been installed in this organization".
Verify dependencies
Confirm the wiring is correct by listing dependencies on each service:
# DID Service dependencies
curl -X GET \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-main/did-service-api/dids/dependencies/list' \
-H 'Authorization: Bearer {yourToken}'
# Expected: ["waltid.tenant1.kms-main", "waltid.tenant1.did-store-main"]
# DID Registry dependencies
curl -X GET \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-registry-main/did-registry-service-api/dependencies/list' \
-H 'Authorization: Bearer {yourToken}'
# Expected: ["waltid.tenant1.did-store-main"]
Tenant vs organization level
Both registry and DID service instances are scoped to a path in the organization tree. Placement determines resolution URLs — there is no separate "tenant-level" or "organization-level" service type.
| Placement | Service path example | Resolution URL |
|---|---|---|
| Inside a tenant | waltid.tenant1.did-registry-main | GET /v1/{target}/did-registry-service-api/registry/{id}/did.json (on the {orgID} host, {target} = the registry's full path) |
| At organization root | waltid.did-registry-main | GET /{id}/did.json (on the {orgID} host, with rootDidRegistry set) |
Choosing a placement:
- Organization root — Use when DIDs represent the org itself (e.g. a central issuer DID). Set the service path directly under the org (
waltid.did-registry-main) and configurerootDidRegistry. - Inside a tenant — Use when each tenant needs isolated DIDs. Place the registry under the tenant path (
waltid.tenant1.did-registry-main).
The path parameter when creating a did:web controls the {id} segment at resolution time, independent of where the registry service lives. For example, path: "users/alice" produces {id} = users:alice.
Next steps
- Create did:web — Generate a DID and store its document
- Resolution — Verify public
did.jsonaccess
