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.

CURL

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 is waltid.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

CURL

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 is waltid.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

CURL

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 is waltid.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

CURL

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 is waltid.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

CURL

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 is waltid.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

CURL

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 is waltid.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:

CURL

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 is waltid.enterprise-sandbox.waltid.dev. This endpoint always operates on whichever organization orgID resolves 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.

PlacementService path exampleResolution URL
Inside a tenantwaltid.tenant1.did-registry-mainGET /v1/{target}/did-registry-service-api/registry/{id}/did.json (on the {orgID} host, {target} = the registry's full path)
At organization rootwaltid.did-registry-mainGET /{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 configure rootDidRegistry.
  • 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

Last updated on August 18, 2026