Watched domains
A watched domain is any domain, hosted here or at another provider, whose nameservers, DNSSEC chain, e-mail records, registration, certificates and availability we keep an eye on. No nameserver change is needed; proving ownership once is.
Scopes
monitor:read to read and monitor:write to change anything. They are not included when you create a key without an explicit scopes list: ask for them on purpose. A zone:* key gets 403 api_key_scope_missing here, and that separation is deliberate: registering a watched domain consumes plan quota and starts continuous probing of someone else's network on your behalf.Ownership comes first
A public one-off diagnosis (/v1/diagnose) needs no login. Continuous watching is a different thing: it creates recurring load on third parties (RDAP, CT logs) in our name and, without a proven owner, would turn the platform into a way to watch other people's portfolios. So a new domain arrives verified: false and nothing is probed until the TXT record is published and confirmed.
A domain that is also an active zone here arrives verified: an active zone already required delegation plus proven ownership, and asking for a second proof would be paperwork with no gain.
The watched domain object
| Field | Type | Description |
|---|---|---|
id | integer | Unique identifier of the watched domain. |
name | string | Domain, normalized to lowercase without trailing dot. |
verified | boolean | Whether ownership has been proven. Nothing is probed until this is true. |
verify_host | string | null | What to type in the "Name" field of most DNS panels (they append the domain themselves). |
verify_record | string | null | The full record name, for panels that expect it. Pasting this one into a panel that appends produces _quathos-verify.example.com.example.com: the most common mistake, and the quietest. |
verify_value | string | null | The TXT value to publish. Disappears from the response once verified. |
current_ns | string[] | Nameservers answering for the domain today; useful to tell the user which panel to publish the TXT in. |
zone_id | integer | null | Linked zone, when the same domain is also hosted here. |
counts_against_quota | boolean | False for domains also served here: those are watched for free on every plan. |
enabled | boolean | Whether the domain is being watched. |
checks | object[] | One entry per check (only on the single-domain route). See below. |
The check object
Returned inside checks on the single-domain route.
| Field | Type | Description |
|---|---|---|
check_kind | enum | ns_delegation · dnssec_ds · dnssec_sig_expiry · spf · dmarc · mx · registrar_expiry · tls_expiry · cert_issued · http_reachable |
family | enum | dns · registry · tls · availability: which surface of the domain the check belongs to. Seven of the ten are not DNS. |
status | enum | ok · warn · fail · unknown. "unknown" means not measured: it never raises an alert and never clears one. |
observed | object | null | What was seen on the last measurement, shaped per check. |
changed | boolean | What is observed now differs from the baseline the account accepted as normal. |
last_checked_at | datetime | null | Last measurement (UTC). |
last_error | string | null | Why the last measurement could not be made. |
unknown is not a failure
unknown with a reason. They never open an alert and never close one. A false alert here is worse than a missing one: it teaches the account to ignore the next.Add domains to the portfolio
/orgs/{org_id}/watched-domainsAdds up to 100 domains in one call and returns them with the TXT record to publish.
Body parameters
| Parameter | Type | Description |
|---|---|---|
names required | string[] | 1 to 100 domains. The whole batch is all-or-nothing: if one name busts the quota, none are added. |
Example
curl -X POST "https://api.monitor.quathos.com/v1/orgs/$ORG_ID/watched-domains" \
-H "Authorization: Bearer $QUATHOS_KEY" \
-H "Content-Type: application/json" \
-d '{ "names": ["example.com"] }'[
{
"id": 17,
"name": "example.com",
"verified": false,
"verify_host": "_quathos-verify",
"verify_record": "_quathos-verify.example.com",
"verify_value": "qx-8Kd2v...",
"current_ns": ["ns1.otherprovider.net", "ns2.otherprovider.net"],
"zone_id": null,
"counts_against_quota": true,
"enabled": true,
"checks": []
}
]Quota is checked per name, and the batch is atomic
409 watched_domain_exists; an invalid name, 422 watched_domain_invalid. Busting the plan quota returns 422 with X-Error-Code: monitor_quota_reached and nothing is added: a portfolio of fifty does not get halfway in because the tenth name hit the ceiling. Domains also served here as a zone never count against quota.Verify ownership
/orgs/{org_id}/watched-domains/{domain_id}/verifyReads the TXT record and flips the domain to verified. Watching starts on the next tick, not on the next scheduled cycle. Idempotent: once verified, it stays verified.
curl -X POST "https://api.monitor.quathos.com/v1/orgs/$ORG_ID/watched-domains/17/verify" \
-H "Authorization: Bearer $QUATHOS_KEY"Give DNS a moment
409 watched_domain_txt_missing while the record is not visible yet. We ask the domain's own nameservers with recursion disabled, so there is no resolver cache between us and the truth, but the record still has to exist at the provider. Poll every few seconds, not in a tight loop.List & retrieve
/orgs/{org_id}/watched-domainsThe portfolio, without the checks.
/orgs/{org_id}/watched-domains/{domain_id}One domain with its checks, ordered by family (DNS, registry, TLS, availability) and then by the catalog order: the same order everywhere.
curl "https://api.monitor.quathos.com/v1/orgs/$ORG_ID/watched-domains/17" \
-H "Authorization: Bearer $QUATHOS_KEY"{
"id": 17,
"name": "example.com",
"verified": true,
"verify_host": null,
"verify_record": null,
"verify_value": null,
"current_ns": ["ns1.otherprovider.net", "ns2.otherprovider.net"],
"zone_id": null,
"counts_against_quota": true,
"enabled": true,
"checks": [
{
"check_kind": "ns_delegation",
"family": "dns",
"status": "ok",
"observed": { "nameservers": ["ns1.otherprovider.net", "ns2.otherprovider.net"] },
"changed": false,
"last_checked_at": "2026-09-12T18:20:04.551302",
"last_error": null
},
{
"check_kind": "http_reachable",
"family": "availability",
"status": "fail",
"observed": { "url": "https://example.com/", "status_code": 502, "reason": "HTTP 502" },
"changed": false,
"last_checked_at": "2026-09-12T18:20:06.019874",
"last_error": null
}
]
}Accept an expected change
/orgs/{org_id}/watched-domains/{domain_id}/acknowledgeWhoever changed nameservers on purpose does not want the same warning forever. This makes what is observed now the new baseline and closes the alert. Returns 409 monitor_check_invalid if the check has never been measured.
Body parameters
| Parameter | Type | Description |
|---|---|---|
check_kind required | string | Which check to accept. What is observed now becomes the new baseline and the alert closes. |
curl -X POST "https://api.monitor.quathos.com/v1/orgs/$ORG_ID/watched-domains/17/acknowledge" \
-H "Authorization: Bearer $QUATHOS_KEY" \
-H "Content-Type: application/json" \
-d '{ "check_kind": "ns_delegation" }'Stop watching
/orgs/{org_id}/watched-domains/{domain_id}Removes the domain from the portfolio, with its checks, hosts and open alerts. Returns 204 No Content and frees the quota slot.
curl -X DELETE "https://api.monitor.quathos.com/v1/orgs/$ORG_ID/watched-domains/17" \
-H "Authorization: Bearer $QUATHOS_KEY"