---
title: "Create did:web"
description: "All did:web creation goes through the DID Service. The service automatically writes the created DID into all linked DID Stores — the DID Registry picks it up from there at resolution time."
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/create-did-web
generated: 2026-10-01
---
# Create did:web

All `did:web` creation goes through the DID Service. The service automatically writes the created DID into all linked DID Stores — the DID Registry picks it up from there at resolution time.

## Prerequisites

Before you begin, ensure you have:

- A [KMS](https://docs.walt.id/enterprise-stack/services/key-management-service/overview.md) service with a generated key.
- A [DID Service](https://docs.walt.id/enterprise-stack/services/did-registry/setup.md) created with **KMS** and **DID Store** dependencies attached.
- A `domain` (and `path`, if you use one) that match the resolution URL you intend to serve — see [Resolution](https://docs.walt.id/enterprise-stack/services/did-registry/resolution.md).

---

**Error:**

`single_key_reference` and `key_reference_set` assign every provided key to **all** verification relationships, including `keyAgreement`. An **Ed25519** key cannot be used for `keyAgreement`, so passing an Ed25519 `keyReference` to either of these two creation types fails with `400 Invalid key type Ed25519 specified for keyAgreement property.` Use a key type that supports ECDH (e.g. `secp256k1`, `secp256r1`), or use `verification_key_reference_set_config` to keep an Ed25519 key out of `keyAgreement` entirely.

## Single key

The simplest case: one key from KMS acts as the verification method for all relationships.

**Option: CURL**

Endpoint: `POST /v1/{target}/did-service-api/dids/create/web` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/DID%20Service%20%7C%20DID%20Service%20API/post_v1__target__did-service-api_dids_create_web)

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-main/did-service-api/dids/create/web' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "single_key_reference",
  "domain": "waltid.enterprise.localhost",
  "path": "users/alice",
  "keyReference": "waltid.tenant1.kms-main.key-alice-1"
}'
```

**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 path, e.g. `waltid.tenant1.did-main`.

**Header Parameters**

- **Authorization**: _String_ (required) - Bearer token for Enterprise Stack authentication. Format: `Bearer {token}`.

**Body Parameters**

- `type` — Must be `"single_key_reference"`.
- `domain` — _String_ (required) - Domain component of the `did:web` identifier.
- `path` — _String_ (optional) - Path component; segments become colon-separated in the DID.
- `keyReference` — _String_ (required) - Full resource path of a key in the linked KMS. Must not be an Ed25519 key (see the callout above). A `key` object (inline JWK) can be provided instead — see [DID Service → DID Web](https://docs.walt.id/enterprise-stack/services/did-service/did-creation/did-web.md) for that shape.
- `didId` — _String_ (optional) - Storage key for the DID within the linked DID Store. If omitted, the DID string is sanitized (`.` replaced with `_`; `:` is kept) and used as the key — e.g. `did:web:waltid.enterprise.localhost:users:alice` becomes `did:web:waltid_enterprise_localhost:users:alice`.

---

**Response** `201 Created` (new DID) or `200 OK` (already existed)

```json
{
  "id": "waltid.tenant1.did-store-main.did:web:waltid_enterprise_localhost:users:alice",
  "did": "did:web:waltid.enterprise.localhost:users:alice",
  "document": {
    "@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/jws-2020/v1"],
    "id": "did:web:waltid.enterprise.localhost:users:alice",
    "verificationMethod": [{
      "id": "did:web:waltid.enterprise.localhost:users:alice#key-1",
      "type": "JsonWebKey2020",
      "controller": "did:web:waltid.enterprise.localhost:users:alice",
      "publicKeyJwk": { }
    }],
    "authentication": ["did:web:waltid.enterprise.localhost:users:alice#key-1"],
    "assertionMethod": ["did:web:waltid.enterprise.localhost:users:alice#key-1"],
    "capabilityDelegation": ["did:web:waltid.enterprise.localhost:users:alice#key-1"],
    "capabilityInvocation": ["did:web:waltid.enterprise.localhost:users:alice#key-1"],
    "keyAgreement": ["did:web:waltid.enterprise.localhost:users:alice#key-1"]
  }
}
```

The resulting DID is `did:web:waltid.enterprise.localhost:users:alice` — path segments from `users/alice` are colon-separated.

## Multiple keys

All keys from KMS become separate `verificationMethod` entries in the document, and **every** key is assigned to **every** verification relationship (`authentication`, `assertionMethod`, `keyAgreement`, `capabilityInvocation`, `capabilityDelegation`) — this mode does not let you dedicate a specific key to a specific relationship. Use [Keys with explicit verification relationships](#keys-with-explicit-verification-relationships) below for that.

**Option: CURL**

Endpoint: `POST /v1/{target}/did-service-api/dids/create/web` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/DID%20Service%20%7C%20DID%20Service%20API/post_v1__target__did-service-api_dids_create_web)

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-main/did-service-api/dids/create/web' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "key_reference_set",
  "domain": "waltid.enterprise.localhost",
  "path": "org/issuer",
  "keyReferenceSet": [
    "waltid.tenant1.kms-main.key-sign-1",
    "waltid.tenant1.kms-main.key-encrypt-1"
  ]
}'
```

**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 path, e.g. `waltid.tenant1.did-main`.

**Header Parameters**

- **Authorization**: _String_ (required) - Bearer token for Enterprise Stack authentication. Format: `Bearer {token}`.

**Body Parameters**

- `type` — Must be `"key_reference_set"`.
- `domain` — _String_ (required) - Domain component of the `did:web` identifier.
- `path` — _String_ (optional) - Path component.
- `keyReferenceSet` — _Array of Strings_ (required) - Full resource paths of keys in the linked KMS. None may be an Ed25519 key (see the callout above). A `keySet` array (inline JWKs) can be provided instead.
- `didId` — _String_ (optional) - Storage key for the DID within the linked DID Store. If omitted, the DID string is sanitized (`.` replaced with `_`; `:` is kept) and used as the key — e.g. `did:web:waltid.enterprise.localhost:users:alice` becomes `did:web:waltid_enterprise_localhost:users:alice`.

## Keys with explicit verification relationships

Full control over which key appears under which verification relationship. Relationships not listed in `verificationKeyReferenceSetConfiguration` are simply omitted from the document — you don't need to provide all five.

**Option: CURL**

Endpoint: `POST /v1/{target}/did-service-api/dids/create/web` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/DID%20Service%20%7C%20DID%20Service%20API/post_v1__target__did-service-api_dids_create_web)

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-main/did-service-api/dids/create/web' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "verification_key_reference_set_config",
  "domain": "waltid.enterprise.localhost",
  "path": "org/verifier",
  "verificationKeyReferenceSetConfiguration": {
    "authentication": [
      "waltid.tenant1.kms-main.key-auth-1"
    ],
    "assertionMethod": [
      "waltid.tenant1.kms-main.key-assert-1"
    ],
    "keyAgreement": [
      "waltid.tenant1.kms-main.key-agree-1"
    ]
  }
}'
```

**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 path, e.g. `waltid.tenant1.did-main`.

**Header Parameters**

- **Authorization**: _String_ (required) - Bearer token for Enterprise Stack authentication. Format: `Bearer {token}`.

**Body Parameters**

- `type` — Must be `"verification_key_reference_set_config"`.
- `domain` — _String_ (required) - Domain component of the `did:web` identifier.
- `path` — _String_ (optional) - Path component.
- `verificationKeyReferenceSetConfiguration` — _Object_ (required) - Map of relationship name to an array of key resource paths. Supported relationship types: `authentication`, `assertionMethod`, `keyAgreement`, `capabilityInvocation`, `capabilityDelegation`. Any key placed under `keyAgreement` must not be an Ed25519 key (see the callout above).
- `didId` — _String_ (optional) - Storage key for the DID within the linked DID Store. If omitted, the DID string is sanitized (`.` replaced with `_`; `:` is kept) and used as the key — e.g. `did:web:waltid.enterprise.localhost:users:alice` becomes `did:web:waltid_enterprise_localhost:users:alice`.

## With service endpoints

Any of the three creation types accepts a `serviceConfigurationSet` to embed service endpoints in the DID Document. Each entry's `serviceEndpoint` is an **array** of URLs (or endpoint objects), not a single string — and each service entry's `id` is always auto-generated by the server as `{did}#{randomUUID}`; you cannot set it yourself.

**Option: CURL**

Endpoint: `POST /v1/{target}/did-service-api/dids/create/web` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/DID%20Service%20%7C%20DID%20Service%20API/post_v1__target__did-service-api_dids_create_web)

```bash
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v1/waltid.tenant1.did-main/did-service-api/dids/create/web' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "single_key_reference",
  "domain": "waltid.enterprise.localhost",
  "path": "org/issuer",
  "keyReference": "waltid.tenant1.kms-main.key-issuer-1",
  "serviceConfigurationSet": [
    {
      "type": "LinkedDomains",
      "serviceEndpoint": ["https://waltid.enterprise.localhost"]
    },
    {
      "type": "CredentialService",
      "serviceEndpoint": ["https://waltid.enterprise.localhost/credentials"]
    }
  ]
}'
```

**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 path, e.g. `waltid.tenant1.did-main`.

**Header Parameters**

- **Authorization**: _String_ (required) - Bearer token for Enterprise Stack authentication. Format: `Bearer {token}`.

**Body Parameters**

- `serviceConfigurationSet` — _Array of Objects_ (optional) - Each object:
  - `type` — _String_ (required) - Service type, e.g. `"LinkedDomains"`, `"CredentialService"`.
  - `serviceEndpoint` — _Array_ (required) - One or more endpoint URLs (strings) or endpoint objects. A bare string (not wrapped in an array) fails to deserialize.
- `didId` — _String_ (optional) - Storage key for the DID within the linked DID Store. If omitted, the DID string is sanitized (`.` replaced with `_`; `:` is kept) and used as the key — e.g. `did:web:waltid.enterprise.localhost:users:alice` becomes `did:web:waltid_enterprise_localhost:users:alice`.

---

**Response** `201 Created` — the resulting document's `service` entries have server-generated `id`s:

```json
{
  "service": [
    {
      "id": "did:web:waltid.enterprise.localhost:org:issuer#59cc7450-a15f-4400-8edf-ce379c807049",
      "type": "LinkedDomains",
      "serviceEndpoint": "https://waltid.enterprise.localhost"
    },
    {
      "id": "did:web:waltid.enterprise.localhost:org:issuer#93fb034c-0039-4983-8e63-0bf211032628",
      "type": "CredentialService",
      "serviceEndpoint": "https://waltid.enterprise.localhost/credentials"
    }
  ]
}
```

## Next steps

- [Resolution](https://docs.walt.id/enterprise-stack/services/did-registry/resolution.md) — Verify the DID document is publicly accessible
- [External DID Web Hosting](https://docs.walt.id/enterprise-stack/services/did-registry/external-did-web-hosting.md) — Serve on a custom domain

For `did:key` and `did:jwk` creation (which do not use the registry), see the [DID Service docs](https://docs.walt.id/enterprise-stack/services/did-service/did-creation/did-key.md).
