Domain linking
Overview
Domain Linkage connects a decentralized identifier (DID) to a web origin using the Well-Known DID Configuration standard (DIF / W3C VC). It’s a two-step flow that this service automates end-to-end:
Generate (Issue) Domain Linkage — You request a Domain Linkage Credential (DLC) for an HTTPS origin. The service returns a ready-to-host
did-configuration.json. You must publish exactly that JSON at:
<origin>/.well-known/did-configuration.jsonVerify Domain Linkage — You ask the service to verify the published file. The service fetches it, validates that at least one embedded DLC binds your DID to your origin, and on success updates your DID Document on-chain by adding the origin to
alsoKnownAsand ensuring a canonicalLinkedDomainsservice (withserviceEndpoint.origins).
Origin definition (precise): an HTTPS origin is exactly https://<host>[:<port>]. It is only scheme + host + optional non-443 port. Allowed: https://example.com, https://sub.example.com, https://example.com:8443
Endpoints
1) Issue a Domain Linkage Credential
POST /api/v1/domain-linkages
Creates a Domain Linkage Credential (DLC) for the given origin and returns a complete did-configuration.json to host at your site.
Request
{
"domain": "https://example.com",
"expirationDays": 90
}domain: HTTPS origin only (as defined above).expirationDays: integer (e.g., 1..10000).
Response (201)
{
"didConfiguration": {
"@context": "https://identity.foundation/.well-known/did-configuration/v1",
"linked_dids": [
{ /* Verifiable Credential (includes "DomainLinkageCredential") with JWS proof */ }
]
},
"publishAt": "https://example.com/.well-known/did-configuration.json",
"expiresAt": "2026-10-16T10:00:00.000Z"
}What to publish (important): Host only the JSON inside didConfiguration verbatim at the publishAt URL.
cURL
curl -X POST "https://issuer.example/api/v1/domain-linkages" \
-H "Authorization: Bearer $CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"domain":"https://example.com","expirationDays":90}'2) Publish the well-known file
Place the exact didConfiguration JSON at:
https://example.com/.well-known/did-configuration.jsonIf your origin includes a non-default port, publish under that origin (e.g., https://example.com:8443/.well-known/did-configuration.json). No extra wrapping, no renaming, no added fields.
3) Verify & Update DID Document
POST /api/v1/domain-linkages/verify
Fetches your well-known file, validates at least one embedded DLC against your DID Document, and updates your DID Document on-chain to include the origin.
Request
{
"domain": "https://example.com"
}Response (200)
{
"did": "did:empe:xyz...abc"
}On success (side-effects)
Adds the origin to
alsoKnownAs(de-duplicated).Ensures a single canonical service entry:
{ "id": "did:empe:xyz...abc#linked-domains", "type": "LinkedDomains", "serviceEndpoint": { "origins": ["https://example.com", "..."] } }Anchors the updated DID Document to the Empe blockchain (version increment). Note: Your DID should already be anchored for this update to succeed.
cURL
curl -X POST "https://issuer.example/api/v1/domain-linkages/verify" \
-H "Authorization: Bearer $CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"domain":"https://example.com"}'The file you publish (did-configuration.json) — minimal, correct shape
did-configuration.json) — minimal, correct shapePublish exactly this shape (the “Issue” endpoint fills in the values for you):
{
"@context": "https://identity.foundation/.well-known/did-configuration/v1",
"linked_dids": [
{
"@context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiableCredential", "DomainLinkageCredential"],
"issuer": { "id": "did:empe:xyz...abc" },
"issuanceDate": "2025-10-16T10:00:00Z",
"expirationDate": "2026-10-16T10:00:00Z",
"credentialSubject": {
"id": "did:empe:xyz...abc",
"origin": "https://example.com"
},
"proof": {
"type": "JsonWebSignature2020",
"verificationMethod": "did:empe:xyz...abc#keys-1",
"proofPurpose": "assertionMethod",
"created": "2025-10-16T10:00:00Z",
"jws": "<compact-jws>"
}
}
]
}Notes
You may include multiple DLCs in
linked_dids(e.g., key rotation).Different ports mean different origins (
https://example.comvshttps://example.com:8443) and must be issued, published, and verified separately.
Last updated