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 service with a generated key.
- A DID Service created with KMS and DID Store dependencies attached.
- A
domain(andpath, if you use one) that match the resolution URL you intend to serve — see Resolution.
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.
Endpoint: POST /v1/{target}/did-service-api/dids/create/web | API Reference
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 iswaltid.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 thedid:webidentifier.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). Akeyobject (inline JWK) can be provided instead — see DID Service → DID Web 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:alicebecomesdid:web:waltid_enterprise_localhost:users:alice.
Response 201 Created (new DID) or 200 OK (already existed)
{
"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 below for that.
Endpoint: POST /v1/{target}/did-service-api/dids/create/web | API Reference
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 iswaltid.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 thedid:webidentifier.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). AkeySetarray (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:alicebecomesdid: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.
Endpoint: POST /v1/{target}/did-service-api/dids/create/web | API Reference
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 iswaltid.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 thedid:webidentifier.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 underkeyAgreementmust 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:alicebecomesdid: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.
Endpoint: POST /v1/{target}/did-service-api/dids/create/web | API Reference
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 iswaltid.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:alicebecomesdid:web:waltid_enterprise_localhost:users:alice.
Response 201 Created — the resulting document's service entries have server-generated ids:
{
"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 — Verify the DID document is publicly accessible
- External DID Web Hosting — Serve on a custom domain
For did:key and did:jwk creation (which do not use the registry), see the DID Service docs.
