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:

  1. 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.json
  1. Verify 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 alsoKnownAs and ensuring a canonical LinkedDomains service (with serviceEndpoint.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.json

If 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

Publish 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.com vs https://example.com:8443) and must be issued, published, and verified separately.

Last updated