The `POST /v1/dmarc-upgrade` response — the MCP tool result, key for key. Declared explicitly (rather than left as a bare dict) so `/openapi.json` documents the real shape, including the nullability that carries the contract: `record` is null on every honest refusal — the answer is then `rationale`, and a caller must NEVER compose a record to fill the gap. `policy` names the policy the RETURNED record sets, so it is null exactly when `record` is; the domain's observed policy travels in `current_policy` (also null when no DMARC record could be read). The field set mirrors `mcp_server/tools.py::build_dmarc_upgrade_tool` — the same core both surfaces run — so the REST body is byte-equal to the MCP tool result by construction. A key added there is added here.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/dnsdoctor-dev/json-schema/dnsdoctor-dev-dmarc-upgrade-out-schema.json",
"title": "DmarcUpgradeOut",
"description": "The `POST /v1/dmarc-upgrade` response — the MCP tool result, key for key.\n\nDeclared explicitly (rather than left as a bare dict) so `/openapi.json`\ndocuments the real shape, including the nullability that carries the\ncontract: `record` is null on every honest refusal — the answer is then\n`rationale`, and a caller must NEVER compose a record to fill the gap.\n`policy` names the policy the RETURNED record sets, so it is null exactly\nwhen `record` is; the domain's observed policy travels in `current_policy`\n(also null when no DMARC record could be read).\n\nThe field set mirrors `mcp_server/tools.py::build_dmarc_upgrade_tool` — the\nsame core both surfaces run — so the REST body is byte-equal to the MCP tool\nresult by construction. A key added there is added here.",
"x-generated": "2026-11-05",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/dnsdoctor-dev-openapi.json#/components/schemas/DmarcUpgradeOut",
"properties": {
"domain": {
"type": "string",
"title": "Domain"
},
"record": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Record"
},
"policy": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Policy"
},
"current_policy": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Current Policy"
},
"alignment_ok": {
"type": "boolean",
"title": "Alignment Ok"
},
"rationale": {
"type": "string",
"title": "Rationale"
},
"apply_note": {
"type": "string",
"title": "Apply Note"
}
},
"type": "object",
"required": [
"domain",
"record",
"policy",
"current_policy",
"alignment_ok",
"rationale",
"apply_note"
]
}
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.