{"openapi":"3.1.0","info":{"title":"EmailSecOps API","version":"1.0.0","description":"Email authentication posture, DKIM key monitoring, DMARC report analytics and email intelligence. Every check runs on our own resolvers. Authenticate with a team token: `Authorization: Bearer eso_live_\u2026`. Responses wrap results in `data`; lists add `meta`. Monthly quota headers: `X-Quota-Limit`, `X-Quota-Used`."},"servers":[{"url":"https://emailsecops.com/api/v1"}],"security":[{"bearer":[]}],"tags":[{"name":"Account"},{"name":"Domains"},{"name":"DKIM"},{"name":"DMARC"},{"name":"Alerts"},{"name":"Intelligence"},{"name":"Webhooks","description":"Signed per the Standard Webhooks spec: headers `webhook-id`, `webhook-timestamp`, `webhook-signature: v1,<base64 HMAC-SHA256 of \"{id}.{timestamp}.{body}\">` keyed with the base64-decoded part of your `whsec_` secret. Reject timestamps older than 5 minutes; dedupe on `webhook-id`."}],"paths":{"/me":{"get":{"operationId":"getMe","summary":"Team, plan and limits of the token","tags":["Account"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/domains":{"get":{"operationId":"listDomains","summary":"List monitored domains","tags":["Domains"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","maximum":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Domain"}}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"post":{"operationId":"createDomain","summary":"Add a domain (returns the TXT record that proves ownership)","tags":["Domains"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"client_id":{"type":"integer"}},"required":["name"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Domain"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/domains/{domain}":{"get":{"operationId":"getDomain","summary":"Domain with latest posture, recommendations and exact DNS fixes","tags":["Domains"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Domain"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"delete":{"operationId":"deleteDomain","summary":"Remove a domain","tags":["Domains"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"}],"responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/domains/{domain}/verify":{"post":{"operationId":"verifyDomain","summary":"Look for the ownership TXT record now","tags":["Domains"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/domains/{domain}/check":{"post":{"operationId":"runCheck","summary":"Queue a posture check (verified domains)","tags":["Domains"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"}],"responses":{"202":{"description":"Queued"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/domains/{domain}/checks":{"get":{"operationId":"listChecks","summary":"Posture check history","tags":["Domains"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"},{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","maximum":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/domains/{domain}/diffs":{"get":{"operationId":"listDiffs","summary":"Changes between consecutive checks","tags":["Domains"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/domains/{domain}/dkim":{"get":{"operationId":"getDomainDkim","summary":"DKIM selector inventory with key age, health, report evidence and findings","tags":["DKIM"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"},{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":30}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DkimOverview"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/domains/{domain}/dkim/selectors":{"post":{"operationId":"addDkimSelector","summary":"Monitor a selector we cannot discover (looked up immediately)","tags":["DKIM"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"selector":{"type":"string"}},"required":["selector"]}}}},"responses":{"201":{"description":"Added","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DkimSelector"}}}}}},"200":{"description":"Already known","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DkimSelector"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/domains/{domain}/dkim/selectors/{selector}":{"get":{"operationId":"getDkimSelector","summary":"One selector with its key rotation history","tags":["DKIM"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"},{"name":"selector","in":"path","required":true,"schema":{"type":"string"}},{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":30}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DkimSelector"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"delete":{"operationId":"removeDkimSelector","summary":"Stop monitoring a selector you added (409 if it is published)","tags":["DKIM"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"},{"name":"selector","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"409":{"description":"Published or discovered selector"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/dkim/lookup":{"get":{"operationId":"lookupDkim","summary":"Live DKIM check of any domain: one or more selectors, or discovery across common selectors","tags":["DKIM"],"parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string"}},{"name":"selector","in":"query","schema":{"type":"string"}},{"name":"selectors","in":"query","schema":{"type":"string"},"description":"Comma-separated, up to 20. Omit both to scan common selectors."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DkimLookup"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/dkim/verify":{"post":{"operationId":"verifyDkimSignature","summary":"Cryptographically verify every DKIM-Signature of a raw message (body hash and signature)","tags":["DKIM"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Raw RFC 5322 message, headers and body, up to 1 MB"}},"required":["message"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DkimVerification"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/dkim/generate":{"post":{"operationId":"generateDkimKey","summary":"Generate a key pair and the exact TXT record (not stored or logged)","tags":["DKIM"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string"},"selector":{"type":"string"},"algorithm":{"type":"string","enum":["rsa-2048","rsa-1024","rsa-4096","ed25519"],"default":"rsa-2048"}},"required":["domain","selector"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DkimKeyPair"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/domains/{domain}/dmarc":{"get":{"operationId":"getDmarcAdvice","summary":"DMARC report summary, enforcement advice and daily series","tags":["DMARC"],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"integer"},"description":"Domain id"},{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":30}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/alerts":{"get":{"operationId":"listAlerts","summary":"Alerts, newest first","tags":["Alerts"],"parameters":[{"name":"open","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Alert"}}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/alerts/{alert}/resolve":{"post":{"operationId":"resolveAlert","summary":"Mark an alert resolved","tags":["Alerts"],"parameters":[{"name":"alert","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/intel/domain":{"get":{"operationId":"intelDomain","summary":"Full posture of any domain without adding it","tags":["Intelligence"],"parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string"}},{"name":"full","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/intel/email":{"get":{"operationId":"intelEmail","summary":"Risk check of one email address","tags":["Intelligence"],"parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/intel/emails":{"post":{"operationId":"intelEmails","summary":"Risk check of up to 100 addresses","tags":["Intelligence"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"emails":{"type":"array","items":{"type":"string"},"maxItems":100}},"required":["emails"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/webhook-events":{"get":{"operationId":"listWebhookEvents","summary":"Event types an endpoint can subscribe to","tags":["Webhooks"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/webhooks":{"get":{"operationId":"listWebhooks","summary":"Webhook endpoints (meta.limit = plan allowance)","tags":["Webhooks"],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"post":{"operationId":"createWebhook","summary":"Create an endpoint; the signing secret is returned once","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"description":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"domain_ids":{"type":"array","items":{"type":"integer"}}},"required":["url","events"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/webhooks/{webhook}":{"get":{"operationId":"getWebhook","summary":"One endpoint","tags":["Webhooks"],"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"patch":{"operationId":"updateWebhook","summary":"Change URL, events, domains or enabled","tags":["Webhooks"],"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"description":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"domain_ids":{"type":"array","items":{"type":"integer"}},"enabled":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}},"delete":{"operationId":"deleteWebhook","summary":"Delete an endpoint and its delivery log","tags":["Webhooks"],"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/webhooks/{webhook}/test":{"post":{"operationId":"testWebhook","summary":"Send a webhook.test event now","tags":["Webhooks"],"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"202":{"description":"Sent","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookDelivery"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/webhooks/{webhook}/rotate-secret":{"post":{"operationId":"rotateWebhookSecret","summary":"New secret; the old one keeps signing for 24 hours","tags":["Webhooks"],"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/webhooks/{webhook}/deliveries":{"get":{"operationId":"listWebhookDeliveries","summary":"Delivery log (30 days)","tags":["Webhooks"],"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"integer"}},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","delivered","failed"]}},{"name":"event","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"per_page","in":"query","schema":{"type":"integer","maximum":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/webhooks/{webhook}/deliveries/{delivery}":{"get":{"operationId":"getWebhookDelivery","summary":"One delivery with payload and response","tags":["Webhooks"],"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"integer"}},{"name":"delivery","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookDelivery"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/webhooks/{webhook}/deliveries/{delivery}/redeliver":{"post":{"operationId":"redeliverWebhook","summary":"Send a delivery again (same webhook-id, new signature)","tags":["Webhooks"],"parameters":[{"name":"webhook","in":"path","required":true,"schema":{"type":"integer"}},{"name":"delivery","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"202":{"description":"Queued","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookDelivery"}}}}}},"401":{"$ref":"#/components/responses/Unauthenticated"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}}},"webhooks":{"domain.created":{"post":{"summary":"domain.created","description":"A domain was added to the team.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"domain.created"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"domain.created"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"domain.verified":{"post":{"summary":"domain.verified","description":"Domain ownership was verified; monitoring started.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"domain.verified"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"domain.verified"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"domain.deleted":{"post":{"summary":"domain.deleted","description":"A domain was removed.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"domain.deleted"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"domain.deleted"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"check.completed":{"post":{"summary":"check.completed","description":"A posture check finished (every run, with score and grade).","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"check.completed"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"check.completed"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"posture.changed":{"post":{"summary":"posture.changed","description":"A check found differences from the previous one (all changes in one event).","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"posture.changed"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"posture.changed"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"dkim.selector.added":{"post":{"summary":"dkim.selector.added","description":"A new DKIM selector was published.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"dkim.selector.added"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"dkim.selector.added"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"dkim.selector.removed":{"post":{"summary":"dkim.selector.removed","description":"A DKIM selector no longer resolves.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"dkim.selector.removed"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"dkim.selector.removed"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"dkim.key.rotated":{"post":{"summary":"dkim.key.rotated","description":"The public key behind a DKIM selector changed.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"dkim.key.rotated"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"dkim.key.rotated"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"dkim.key.revoked":{"post":{"summary":"dkim.key.revoked","description":"A DKIM key was revoked (empty p=).","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"dkim.key.revoked"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"dkim.key.revoked"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"dkim.record.changed":{"post":{"summary":"dkim.record.changed","description":"A DKIM record changed without a new key (flags, tags).","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"dkim.record.changed"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"dkim.record.changed"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"dkim.key.stale":{"post":{"summary":"dkim.key.stale","description":"A DKIM key has been published longer than the rotation threshold (daily audit).","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"dkim.key.stale"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"dkim.key.stale"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"dns.record.changed":{"post":{"summary":"dns.record.changed","description":"An SPF, DMARC, BIMI, MTA-STS, TLS-RPT or MX record changed.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"dns.record.changed"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"dns.record.changed"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"blacklist.listed":{"post":{"summary":"blacklist.listed","description":"A domain or sending IP was listed on a DNS blacklist.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"blacklist.listed"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"blacklist.listed"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"blacklist.delisted":{"post":{"summary":"blacklist.delisted","description":"A listing was cleared.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"blacklist.delisted"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"blacklist.delisted"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"alert.created":{"post":{"summary":"alert.created","description":"An alert was raised (drift, blacklist, DMARC failure spike, expiry, DKIM finding).","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"alert.created"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"alert.created"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"alert.resolved":{"post":{"summary":"alert.resolved","description":"An alert was marked resolved.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"alert.resolved"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"alert.resolved"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"dmarc.report.received":{"post":{"summary":"dmarc.report.received","description":"A DMARC aggregate report was ingested.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"dmarc.report.received"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"dmarc.report.received"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}},"webhook.test":{"post":{"summary":"webhook.test","description":"Sent by the \"send test event\" action.","parameters":[{"name":"webhook-id","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-EmailSecOps-Event","in":"header","schema":{"type":"string","const":"webhook.test"}}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEvent"},{"type":"object","properties":{"type":{"const":"webhook.test"}}}]}}}},"responses":{"2XX":{"description":"Accepted. Anything else is retried (5xx, 408, 425, 429, timeouts) or recorded as failed (other 4xx)."}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Team API token (eso_live_\u2026), or an OAuth access token for MCP clients."}},"responses":{"Unauthenticated":{"description":"Missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TooManyRequests":{"description":"Rate limit (per minute) or monthly quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","properties":{"message":{"type":"string"}}},"Domain":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"client":{"type":["string","null"]},"verified":{"type":"boolean"},"score":{"type":["integer","null"]},"grade":{"type":["string","null"]},"dmarc_policy":{"type":["string","null"]},"last_checked_at":{"type":["string","null"],"format":"date-time"},"next_check_at":{"type":["string","null"],"format":"date-time"}}},"DkimKey":{"type":["object","null"],"properties":{"type":{"type":"string"},"bits":{"type":["integer","null"]},"fingerprint":{"type":"string"},"testing":{"type":"boolean"},"first_seen_at":{"type":["string","null"],"format":"date-time"},"age_days":{"type":["integer","null"]},"age_bucket":{"type":["string","null"],"enum":["under_6_months","over_6_months","over_2_years",null]}}},"DkimSelector":{"type":"object","properties":{"selector":{"type":"string"},"host":{"type":"string"},"status":{"type":"string","enum":["active","invalid","revoked","missing","pending"]},"health":{"type":"string","enum":["pass","warning","fail"]},"source":{"type":"string","enum":["discovered","manual","dmarc"]},"provider":{"type":["string","null"]},"delegated_to":{"type":["string","null"]},"key":{"$ref":"#/components/schemas/DkimKey"},"record":{"type":["string","null"]},"rotations":{"type":"integer"},"issues":{"type":"array","items":{"type":"object","properties":{"rule":{"type":"string"},"severity":{"type":"string","enum":["Critical","High","Medium","Low","Info"]},"description":{"type":"string"},"fix":{"type":["string","null"]}}}},"first_seen_at":{"type":["string","null"],"format":"date-time"},"last_seen_at":{"type":["string","null"],"format":"date-time"},"missing_since":{"type":["string","null"],"format":"date-time"},"last_report_at":{"type":["string","null"],"format":"date-time"},"reports":{"type":["object","null"],"properties":{"messages":{"type":"integer"},"pass":{"type":"integer"},"fail":{"type":"integer"},"sources":{"type":"array","items":{"type":"string"}}}},"history":{"type":"array","items":{"type":"object","properties":{"fingerprint":{"type":"string"},"type":{"type":"string"},"bits":{"type":["integer","null"]},"record":{"type":"string"},"first_seen_at":{"type":["string","null"],"format":"date-time"},"last_seen_at":{"type":["string","null"],"format":"date-time"},"retired_at":{"type":["string","null"],"format":"date-time"},"retired_reason":{"type":["string","null"]}}}}}},"DkimOverview":{"type":"object","properties":{"domain":{"type":"string"},"days":{"type":"integer"},"summary":{"type":"object"},"selectors":{"type":"array","items":{"$ref":"#/components/schemas/DkimSelector"}},"signers":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"aligned":{"type":"boolean"},"messages":{"type":"integer"},"pass":{"type":"integer"},"sources":{"type":"array","items":{"type":"string"}}}}},"findings":{"type":"array","items":{"type":"object","properties":{"rule":{"type":"string"},"severity":{"type":"string","enum":["Critical","High","Medium","Low","Info"]},"description":{"type":"string"},"fix":{"type":["string","null"]}}}}}},"DkimLookup":{"type":"object","properties":{"domain":{"type":"string"},"status":{"type":"string"},"score":{"type":"integer"},"summary":{"type":"string"},"scanned":{"type":"integer"},"wildcard":{"type":"boolean"},"selectors":{"type":"object","additionalProperties":{"type":"object"}},"missing":{"type":"object"},"issues":{"type":"array","items":{"type":"object","properties":{"rule":{"type":"string"},"severity":{"type":"string","enum":["Critical","High","Medium","Low","Info"]},"description":{"type":"string"},"fix":{"type":["string","null"]}}}}}},"DkimVerification":{"type":"object","properties":{"result":{"type":"string","enum":["pass","fail","none","permerror","temperror"]},"from_domain":{"type":["string","null"]},"aligned":{"type":"boolean"},"signatures":{"type":"array","items":{"type":"object"}},"warnings":{"type":"array","items":{"type":"string"}}}},"DkimKeyPair":{"type":"object","properties":{"domain":{"type":"string"},"selector":{"type":"string"},"algorithm":{"type":"string"},"dns":{"type":"object","properties":{"host":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"}}},"zone_file":{"type":"string"},"fingerprint":{"type":"string"},"key_bits":{"type":"integer"},"private_key_pem":{"type":"string"}}},"Alert":{"type":"object","properties":{"id":{"type":"integer"},"domain":{"type":["string","null"]},"kind":{"type":"string"},"severity":{"type":"string"},"title":{"type":"string"},"body":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time"},"resolved_at":{"type":["string","null"],"format":"date-time"}}},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"integer"},"url":{"type":"string"},"description":{"type":["string","null"]},"events":{"type":"array","items":{"type":"string"}},"domain_ids":{"type":["array","null"],"items":{"type":"integer"}},"enabled":{"type":"boolean"},"failure_count":{"type":"integer"},"disabled_at":{"type":["string","null"],"format":"date-time"},"disabled_reason":{"type":["string","null"]},"last_success_at":{"type":["string","null"],"format":"date-time"},"last_failure_at":{"type":["string","null"],"format":"date-time"},"secret":{"type":"string","description":"Only on create and rotate"}}},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"integer"},"event_id":{"type":"string"},"event":{"type":"string"},"status":{"type":"string","enum":["pending","delivered","failed"]},"attempts":{"type":"integer"},"response_status":{"type":["integer","null"]},"error":{"type":["string","null"]},"duration_ms":{"type":["integer","null"]},"next_retry_at":{"type":["string","null"],"format":"date-time"},"delivered_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":["string","null"],"format":"date-time"}}},"WebhookEvent":{"type":"object","properties":{"id":{"type":"string","description":"Same as the webhook-id header; stable across retries"},"type":{"type":"string","enum":["domain.created","domain.verified","domain.deleted","check.completed","posture.changed","dkim.selector.added","dkim.selector.removed","dkim.key.rotated","dkim.key.revoked","dkim.record.changed","dkim.key.stale","dns.record.changed","blacklist.listed","blacklist.delisted","alert.created","alert.resolved","dmarc.report.received","webhook.test"]},"api_version":{"type":"string","const":"2026-10-10"},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","description":"Event-specific. Domain events carry data.domain {id, name}."}}}}}}