# 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
```

2. **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**

```json
{
  "domain": "https://example.com",
  "expirationDays": 90
}
```

* `domain`: HTTPS **origin** only (as defined above).
* `expirationDays`: integer (e.g., 1..10000).

**Response (201)**

```json
{
  "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**

```bash
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**

```json
{
  "domain": "https://example.com"
}
```

**Response (200)**

```json
{
  "did": "did:empe:xyz...abc"
}
```

**On success (side-effects)**

* Adds the origin to `alsoKnownAs` (de-duplicated).
* Ensures a single canonical service entry:

  ```json
  {
    "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**

```bash
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):

```json
{
  "@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.
