## GET /api/v2/domains/{id}/dns/diagnostics/origin-compare

**Compare current and historical website origins**

Run a scoped HTTPS origin comparison for one owned domain host. The endpoint resolves current public DNS, probes the current public answer using the requested Host header and SNI, probes the current HostUp web-hosting origin from the DNS zone when available, and probes previous web origins from the latest pre-HostUp DNS snapshot. Use this before telling a customer that Cloudflare/CDN is the root cause: CDN edge IPs are traffic-path evidence, while origin HTTP status shows whether the HostUp origin has website content.

### Related Endpoints

- `GET /api/v2/domains/{id}/dns`: Get domain DNS records
- `GET /api/v2/domains/{id}/dns/audit`: List domain DNS audit events
- `GET /api/v2/domains/{id}/dns/history`: List filtered DNS history

### Headers

- `Accept`: application/json
- `Authorization`: Bearer YOUR_API_KEY
- Required API scopes: `read:dns`, `read:domains`

### Parameters

- `id` (path, string, required): Public domain ID from `GET /api/v2/domains`. Do not invent this value; use the exact ID returned by the referenced API response. Example: `dom_01hxa3b4c5d6e7f8g9h0j1k2m3`
- `host` (query, string): Domain host to compare. Defaults to the domain apex. Must be the domain itself or one of its subdomains, for example `example.se` or `www.example.se`. Example: `example.se`

### Request Example

```bash
curl -X GET "https://cloud.hostup.se/api/v2/domains/dom_01hxa3b4c5d6e7f8g9h0j1k2m3/dns/diagnostics/origin-compare" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
```

### Response Schema

- `host` (string, required)
- `asciiHost` (string, required)
- `checkedAt` (string, required)
- `currentPublic` (object, required)
- `currentPublic.a` (array<string>, required)
- `currentPublic.aaaa` (array<string>, required)
- `currentPublic.cname` (array<string>, required)
- `currentPublic.probedIp` (string,null, required)
- `currentPublic.appearsCdnEdge` (boolean, required)
- `currentPublic.edgeProvider` (string,null, required) Example: `cloudflare`
- `currentPublic.httpStatus` (integer,null, required)
- `currentPublic.server` (string,null, required)
- `currentPublic.bodyBytes` (integer, required)
- `currentPublic.title` (string,null, required)
- `currentPublic.responseMs` (integer, required)
- `currentPublic.errorReason` (string,null, required)
- `hostupOrigin` (null, required)
- `hostupOriginReason` (string,null, required)
- `previousOrigins` (array<object>, required)
- `previousOrigins[].ip` (string, required) Example: `185.113.11.10`
- `previousOrigins[].recordName` (string,null, required) Example: `@`
- `previousOrigins[].recordType` (string, required) Example: `A`
  Allowed values: A, AAAA, CNAME, ALIAS
- `previousOrigins[].target` (string,null, required): CNAME/ALIAS target hostname when the probed IP came from resolving an alias. Example: `null`
- `previousOrigins[].source` (string, required): Origin source, for example `current_hostup_dns_record` or the DNS snapshot source such as `pre_nameserver_change`. Example: `current_hostup_dns_record`
- `previousOrigins[].snapshotId` (string, optional): Snapshot public ID when this origin came from DNS history. Example: `dnss_01hxa3b4c5d6e7f8g9h0j1k2m3`
- `previousOrigins[].capturedAt` (string, optional): Snapshot capture time when this origin came from DNS history. Example: `2026-05-19T09:55:00.000Z`
- `previousOrigins[].providerHint` (string,null, optional): Snapshot provider hint, usually the old authoritative nameserver. Example: `ns1.old-provider.example (203.0.113.10)`
- `previousOrigins[].httpStatus` (integer,null, required) Example: `404`
- `previousOrigins[].server` (string,null, required) Example: `LiteSpeed`
- `previousOrigins[].bodyBytes` (integer, required) Example: `1251`
- `previousOrigins[].title` (string,null, required) Example: `404 Not Found`
- `previousOrigins[].responseMs` (integer, required) Example: `142`
- `previousOrigins[].errorReason` (string,null, required) Example: `null`
- `previousOriginsReason` (string,null, required)
- `diagnosis` (object, required)
- `diagnosis.summary` (string, required)
- `diagnosis.confidence` (string, required)
  Allowed values: high, medium, low
- `diagnosis.evidence` (array<string>, required)

### Responses

#### 200 - Current public, HostUp-origin, and previous-origin HTTPS comparison.
```json
{
  "host": "example.se",
  "asciiHost": "example.se",
  "checkedAt": "2026-05-19T10:30:00.000Z",
  "currentPublic": {
    "a": [
      "104.21.82.230",
      "172.67.207.236"
    ],
    "aaaa": [],
    "cname": [],
    "probedIp": "104.21.82.230",
    "appearsCdnEdge": true,
    "edgeProvider": "cloudflare",
    "httpStatus": 404,
    "server": "cloudflare",
    "bodyBytes": 1251,
    "title": "404 Not Found",
    "responseMs": 188,
    "errorReason": null
  },
  "hostupOrigin": {
    "ip": "185.113.11.10",
    "recordName": "@",
    "recordType": "A",
    "target": null,
    "source": "current_hostup_dns_record",
    "httpStatus": 404,
    "server": "LiteSpeed",
    "bodyBytes": 1251,
    "title": "404 Not Found",
    "responseMs": 142,
    "errorReason": null
  },
  "hostupOriginReason": null,
  "previousOrigins": [
    {
      "ip": "18.208.88.157",
      "recordName": "@",
      "recordType": "A",
      "target": null,
      "source": "pre_nameserver_change",
      "snapshotId": "dnss_01hxa3b4c5d6e7f8g9h0j1k2m3",
      "capturedAt": "2026-05-19T09:55:00.000Z",
      "providerHint": "ns1.old-provider.example (203.0.113.10)",
      "httpStatus": 200,
      "server": "Netlify",
      "bodyBytes": 56057,
      "title": "Example website",
      "responseMs": 210,
      "errorReason": null
    }
  ],
  "previousOriginsReason": null,
  "diagnosis": {
    "summary": "Public DNS appears to use a CDN edge, but the stronger signal is that the HostUp origin returns 404 while a previous origin still returns a working site.",
    "confidence": "high",
    "evidence": [
      "Current public HTTPS response appears to be served through cloudflare.",
      "HostUp origin 185.113.11.10 returned HTTP 404.",
      "Previous origin 18.208.88.157 returned HTTP 200."
    ]
  }
}
```

#### 400 - Invalid host filter.
```json
{
  "type": "https://developer.hostup.se/errors/invalid_request",
  "title": "Validation failed",
  "status": 400,
  "detail": "The request body failed validation.",
  "code": "invalid_request",
  "instance": "/api/v2/orders",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z",
  "errors": [
    {
      "pointer": "/items/0/eppCode",
      "detail": "`eppCode` is required for this transfer.",
      "code": "missing_required"
    }
  ],
  "extensions": {}
}
```

#### 401 - Unauthorized. Authentication is required.
```json
{
  "type": "https://developer.hostup.se/errors/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Authentication is required.",
  "code": "unauthorized",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 403 - Forbidden. The caller lacks a required scope or does not own the resource.
```json
{
  "type": "https://developer.hostup.se/errors/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "The caller lacks a required scope or does not own the resource.",
  "code": "forbidden",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 404 - Not found. The resource does not exist or is not owned by the caller.
```json
{
  "type": "https://developer.hostup.se/errors/not_found",
  "title": "Not found",
  "status": 404,
  "detail": "The requested resource could not be found.",
  "code": "not_found",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 429 - Rate limited. Retry after the limit resets. 429 responses include `Retry-After` seconds plus `X-RateLimit-*` headers.
```json
{
  "type": "https://developer.hostup.se/errors/rate_limit_exceeded",
  "title": "Too many requests",
  "status": 429,
  "detail": "Too many requests. Retry after the limit resets.",
  "code": "rate_limit_exceeded",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 500 - Internal error. Retry later or contact support if the issue persists.
```json
{
  "type": "https://developer.hostup.se/errors/internal_error",
  "title": "Internal server error",
  "status": 500,
  "detail": "An unexpected error occurred. Retry later or contact support if the issue persists.",
  "code": "internal_error",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```
