The message.complained webhook fires when a mailbox provider reports an AhaSend campaign email as spam. The payload holds the feedback type and reporter.
AhaSend sends this event when the recipient’s mailbox provider reports your campaign email as spam through its feedback loop. This event is sent for campaign email only. A spam complaint about a transactional email suppresses the address and sends suppression.created.data.complaint.feedback_type is the feedback type of the report, abuse or fraud. data.complaint.reporter is the feedback loop that sent the report. AhaSend can add feedback loops at any time, so keep a fallback for a value you do not know. data.campaign_id, data.list_id and data.segment_id say which campaign sent the email and how it reached the recipient.Repeats: AhaSend sends this event for every complaint report that it matches to the message, also when the recipient is already unsubscribed. Drop the repeats by type and data.id. The contact events of the same report are sent only when the report changes something, except for a campaign sent to a segment.Setting: on_complained (Message Reported as Spam in the dashboard).When it’s sent: When AhaSend receives a spam complaint report and matches it to the message.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"AhaSend","description":"AhaSend is a European transactional email service for developers: send through a REST API, SMTP relay, CLI or the official Node.js and Go SDKs, with data stored in the EU and 1,000 free emails per month.","colors":{"primary":"#066fd1","light":"#F8FAFC","dark":"#0F172A"},"logo":{"light":"https://mintcdn.com/ahasend/F35Ozd-1GsftDpcH/logo.png?fit=max\u0026auto=format\u0026n=F35Ozd-1GsftDpcH\u0026q=85\u0026s=ca1d4c27f7c2811598e65cb25a21323c","dark":"https://mintcdn.com/ahasend/F35Ozd-1GsftDpcH/logo-dark.png?fit=max\u0026auto=format\u0026n=F35Ozd-1GsftDpcH\u0026q=85\u0026s=bb6b9068b30f93fd1ea216e2a7c1d137","href":"https://ahasend.com/"},"favicon":"https://mintcdn.com/ahasend/F35Ozd-1GsftDpcH/favicon.png?fit=max\u0026auto=format\u0026n=F35Ozd-1GsftDpcH\u0026q=85\u0026s=ac855c16b6cb74b8c5965d2e7ef3e324","appearance":{"strict":false},"navbar":{"links":[{"href":"https://dash.ahasend.com","label":"Login"}],"primary":{"type":"button","label":"Get Started","href":"https://dash.ahasend.com/user/register"}},"footer":{"socials":{"x":"https://x.com/aha_send","linkedin":"https://www.linkedin.com/company/ahasend","github":"https://github.com/ahasend"},"links":[{"header":"Resources","items":[{"label":"Pricing","href":"https://ahasend.com/pricing"},{"label":"Support","href":"mailto:support@ahasend.com"},{"label":"Status","href":"https://status.ahasend.com"},{"label":"Security","href":"https://ahasend.com/security"}]},{"header":"Company","items":[{"label":"Blog","href":"https://ahasend.com/blog"},{"label":"Feedback Board","href":"https://ahasend.sleekplan.app/"}]},{"header":"Legal","items":[{"label":"Imprint","href":"https://ahasend.com/imprint"},{"label":"Terms of Service","href":"https://ahasend.com/terms"},{"label":"Privacy Policy","href":"https://ahasend.com/privacy"},{"label":"Data Processing Agreement","href":"https://ahasend.com/dpa"}]}]},"seo":{"metatags":{"canonical":"https://ahasend.com/docs","twitter:site":"@aha_send"},"organization":{"name":"AhaSend","legalName":"AhaSend B.V.","url":"https://ahasend.com","sameAs":["https://x.com/aha_send","https://www.linkedin.com/company/ahasend","https://github.com/ahasend"]}},"integrations":{"telemetry":{"enabled":true},"cookies":{"key":"cookieConsent","value":"true"}},"errors":{"404":{"redirect":true}},"contextual":{"options":["copy","view","chatgpt","claude"],"display":"header"},"thumbnails":{"appearance":"dark","background":"https://mintcdn.com/ahasend/Gpf8BnLpzpIKQ4dU/images/social-background.svg?fit=max\u0026auto=format\u0026n=Gpf8BnLpzpIKQ4dU\u0026q=85\u0026s=df32e1edef517352b8437c75feecbf6e"},"markdown":{"instructions":["AhaSend stores all message data in the EU. See /facts.","The API base URL is https://api.ahasend.com. Send the API key in the Authorization: Bearer header. See /api-reference/authentication.","Use send.ahasend.com for SMTP. Ports 25, 587 and 2525 use STARTTLS. Port 465 is not supported. See /smtp.","For send-only integrations, create an API Key v2 under Credentials → Add and scope it to messages:send:{your-domain}. See /send-api/credentials and /api-reference/scopes."]},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"ahasend","hasAudioNarration":false,"actualSubdomain":"ahasend","customDomains":["ahasend.com"],"gitSource":{"type":"github","owner":"ahasend","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6adfc319e83fbbb268c93e4e","collectionId":"0d176591-a964-41df-9533-235282892afa","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6adfc319e83fbbb268c93e4e"},"feedback":{"thumbs":true},"entitlements":{},"buildId":"6adfc319e83fbbb268c93e4e","clientVersion":"0.0.3971","searchFilterCounts":[{"language":"default","tag":"API Reference","count":148},{"language":"default","tag":"API reference","count":114},{"language":"default","tag":"Documentation","count":68},{"language":"default","tag":"Guides","count":52},{"language":"default","tag":"Integrations","count":41},{"language":"default","tag":"Webhooks","count":29},{"language":"default","tag":"CLI","count":25},{"language":"default","tag":"Commands","count":15},{"language":"default","tag":"Domain Authentication","count":13},{"language":"default","tag":"Campaigns","count":12}]},"assistantConfig":{},"basePath":"/docs","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-v7-file-tree","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-nav-generations","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-agent-model-picker","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"privacy":{"consentBanner":{"enabled":false}},"isAtlas":false,"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"#content-container table{display:table}#content-container table thead th{text-align:left}"},{"filePath":"roadmap.css","content":".rm{display:flex;flex-direction:column;gap:2.5rem;margin-top:1.5rem}.rm-head{display:flex;align-items:center;gap:.65rem;margin-bottom:1rem}.rm-badge{display:inline-flex;align-items:center;margin:0;border:0;font-size:.78rem;font-weight:600;letter-spacing:.02em;padding:.28rem .75rem;border-radius:999px;line-height:1}.rm-badge.is-active{background:#fdebd0;color:#854f0b}.rm-badge.is-planned{background:#e6f1fb;color:#0c447c}.rm-badge.is-shipped{background:#e1f5ee;color:#0f6e56}.rm-list{display:flex;flex-direction:column;gap:.65rem}.rm-card{display:flex;gap:.9rem;padding:.9rem 1.05rem;background:#fff;border:1px solid #e5e7eb;border-radius:.7rem;transition:transform .15s ease,box-shadow .15s ease}.rm-card:hover{transform:translateY(-1px);box-shadow:0 4px 14px rgba(0,0,0,.06)}.rm-accent{flex:0 0 3px;border-radius:2px}.rm-card.is-active .rm-accent{background:#ba7517}.rm-card.is-planned .rm-accent{background:#378add}.rm-card.is-shipped .rm-accent{background:#1d9e75}.rm-card.is-sub{margin-left:2rem;position:relative}.rm-card p,.rm-card.is-sub .rm-title{font-size:.9rem}.rm-card.is-sub::after,.rm-card.is-sub::before{content:\"\";position:absolute;left:-1.15rem;pointer-events:none}.rm-card.is-sub::before{top:-.65rem;height:calc(100% + .65rem);border-left:1.5px solid #d1d5db}.rm-card.is-sub::after{top:50%;width:.85rem;border-top:1.5px solid #d1d5db}.rm-card .rm-title{margin:0 0 .2rem;font-size:.97rem;font-weight:600;line-height:1.35;color:#111827}.rm-card p{margin:0;line-height:1.55;color:#4b5563}.rm-date,.rm-tag{display:inline-block}.rm-date{margin-top:.5rem;font-size:.78rem;font-weight:600;color:#0f6e56}.rm-tag{margin-left:.5rem;font-size:.66rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;padding:.16rem .5rem;border-radius:999px;vertical-align:middle;line-height:1.4;color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.15)}.rm-tag.is-new{background:#6d28d9}.rm-tag.is-product{background:#be123c}.rm-tag.is-improvement{background:#0e7490}.rm-tag.is-early{background:#1d4ed8}.rm-tag.is-bugfix{background:#c2410c}.dark .rm-card{background:rgba(255,255,255,.025);border-color:rgba(255,255,255,.09)}.dark .rm-card p{color:#9ca3af}.dark .rm-badge.is-active{background:rgba(186,117,23,.18);color:#fac074}.dark .rm-badge.is-planned{background:rgba(55,138,221,.18);color:#85b7eb}.dark .rm-badge.is-shipped{background:rgba(29,158,117,.18);color:#5dcaa5}.dark .rm-date{color:#5dcaa5}.dark .rm-card.is-sub::after,.dark .rm-card.is-sub::before{border-color:rgba(255,255,255,.18)}.rm-note{margin-top:2.5rem;font-size:.85rem;color:#6b7280}.dark .rm-note{color:#9ca3af}.dark .rm-card .rm-title{color:#e7e9ee}.rm-jump{margin:-.5rem 0 0;font-size:.88rem}.rm-jump a{color:#2296ff;text-decoration:none;font-weight:500}.rm-jump a:hover{text-decoration:underline}.rm-badge[id]{scroll-margin-top:6rem}"}],"page":{"pagePath":"api-reference/webhooks/message-complained","slug":"/api-reference/webhooks/message-complained","pageMetadata":{"title":"message.complained Webhook Event","sidebarTitle":"Complained","openapi":"webhooks.yaml webhook message.complained","description":"The message.complained webhook fires when a mailbox provider reports an AhaSend campaign email as spam. The payload holds the feedback type and reporter.","href":"/api-reference/webhooks/message-complained"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"The message.complained webhook fires when a mailbox provider reports an AhaSend campaign email as spam. The payload holds the feedback type and reporter.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{Heading}=_components;if(!Heading)_missingMdxReference(`Heading`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`AhaSend sends this event when the recipient’s mailbox provider reports your campaign email as spam through its feedback loop. This event is sent for campaign email only. A spam complaint about a transactional email suppresses the address and sends `,_jsx(_components.a,{href:`/api-reference/webhooks/suppression-created`,children:_jsx(_components.code,{children:`suppression.created`})}),`.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`data.complaint.feedback_type`}),` is the feedback type of the report, `,_jsx(_components.code,{children:`abuse`}),` or `,_jsx(_components.code,{children:`fraud`}),`. `,_jsx(_components.code,{children:`data.complaint.reporter`}),` is the feedback loop that sent the report. AhaSend can add feedback loops at any time, so keep a fallback for a value you do not know. `,_jsx(_components.code,{children:`data.campaign_id`}),`, `,_jsx(_components.code,{children:`data.list_id`}),` and `,_jsx(_components.code,{children:`data.segment_id`}),` say which campaign sent the email and how it reached the recipient.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Repeats`}),`: AhaSend sends this event for every complaint report that it matches to the message, also when the recipient is already unsubscribed. Drop the repeats by `,_jsx(_components.code,{children:`type`}),` and `,_jsx(_components.code,{children:`data.id`}),`. The `,_jsx(_components.a,{href:`/api-reference/webhooks/contact-complained`,children:`contact events`}),` of the same report are sent only when the report changes something, except for a campaign sent to a segment.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Setting`}),`: `,_jsx(_components.code,{children:`on_complained`}),` (Message Reported as Spam in the dashboard).`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`When it’s sent`}),`: When AhaSend receives a spam complaint report and matches it to the message.`]}),`\n`,_jsx(Heading,{level:`2`,id:`related-guides`,children:`Related Guides`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/api-reference/authentication`,children:`API authentication`}),`, `,_jsx(_components.a,{href:`/api-reference/scopes`,children:`Permission scopes`}),`, `,_jsx(_components.a,{href:`/integrations/webhooks`,children:`Webhook setup`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/api-reference/webhooks`,children:`Event reference`}),`, `,_jsx(_components.a,{href:`/cli/commands/webhooks`,children:`Webhook CLI`}),`, `,_jsx(_components.a,{href:`/cli/webhook-testing`,children:`Local webhook testing`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/api-reference/webhooks/security`,children:`Signature verification`}),`, `,_jsx(_components.a,{href:`/api-reference/webhooks/retry-policy`,children:`Retry policy`}),`, `,_jsx(_components.a,{href:`/api-reference/errors`,children:`API errors`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/api-reference/rate-limits`,children:`API rate limits`}),`, `,_jsx(_components.a,{href:`/api-reference/contacts/overview`,children:`Contacts API`}),`, `,_jsx(_components.a,{href:`/bounces#suppression-duration`,children:`Suppression durations`}),`.`]}),`\n`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"message.complained Webhook Event","sidebarTitle":"Complained","openapi":"webhooks.yaml webhook message.complained","description":"The message.complained webhook fires when a mailbox provider reports an AhaSend campaign email as spam. The payload holds the feedback type and reporter.","href":"/api-reference/webhooks/message-complained"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Related Guides","slug":"related-guides","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/docs/_mintlify/custom/ahasend/1d760da0535d9f7c/ahasend-gtm.js"],"openApiReferenceData":{"operation":{"summary":"Message Complained Event","description":"The message.complained webhook fires when a mailbox provider reports an AhaSend campaign email as spam. The payload holds the feedback type and reporter.","tags":["Message Events"],"requestBody":"98416a09-91f5-4f52-9f90-3893ad1b60ec","responses":{"200":"908a2f93-c538-49a0-a1b6-90378a7fe5a0","201":"ff83c44d-cae4-496e-9b04-211e5808952f","202":"5d0d4e6c-6828-4cc1-b2f8-ff639e3a4366","204":"75842870-5466-4c73-8635-938c1c52ab86"},"method":"post","type":"webhook","servers":["95c7e3b5-e1ae-46d6-9613-a0f4bcec85ed"],"security":[],"path":"message.complained","baseUrlOptions":["https://your-webhook-endpoint.com"],"title":"Message Complained Event","codeSamples":[],"requiredOnlyExamples":false,"requestExamples":[{"language":"json","filename":"Example","code":"{\n \"type\": \"message.complained\",\n \"webhook_id\": \"abe11757-2886-4b55-96f1-0e0afc95795a\",\n \"timestamp\": \"2024-05-06T10:30:16.687031577Z\",\n \"data\": {\n \"account_id\": \"4cdd7bdd-294e-4762-892f-83d40abf5a87\",\n \"event\": \"on_complained\",\n \"from\": \"Example News \u003cnews@example.com>\",\n \"recipient\": \"recipient@example.com\",\n \"subject\": \"Our October news\",\n \"message_id_header\": \"\u003cmessage-id-12345@localhost>\",\n \"id\": \"407926766d2711f09b30960002cafe7c\",\n \"is_bot\": false,\n \"complaint\": {\n \"feedback_type\": \"abuse\",\n \"reporter\": \"yahoo\"\n },\n \"campaign_id\": \"8b0f4c2e-5d1a-4f6b-9c3e-2a7d1e9f0b44\",\n \"list_id\": \"c3e1a9d2-7f4b-4e8a-b5c6-1d2e3f4a5b6c\",\n \"segment_id\": null\n }\n}"}],"requestExampleType":"webhook","responseExampleType":"generated"},"dependencies":{"parameters":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","webhook_id","timestamp","data"],"properties":{"type":{"type":"string","description":"The event type","enum":["message.complained"],"isRequired":true,"uniqueKey":"type","typeLabel":"enum\u003cstring>"},"webhook_id":{"type":"string","description":"The webhook ID (the same ID as returned by the [Create Webhook API](https://ahasend.com/docs/api-reference/webhooks/create-webhook))","format":"uuid","isRequired":true,"uniqueKey":"webhook_id","typeLabel":"string\u003cuuid>"},"timestamp":{"type":"string","format":"date-time","description":"When the event occurred (ISO 8601 format)","isRequired":true,"uniqueKey":"timestamp","typeLabel":"string\u003cdate-time>"},"data":{"type":"object","required":["account_id","event","from","recipient","subject","message_id_header","id"],"properties":{"account_id":{"type":"string","format":"uuid","description":"Account ID that sent the message","isRequired":true,"uniqueKey":"data.account_id","typeLabel":"string\u003cuuid>"},"event":{"type":"string","enum":["on_reception","on_delivered","on_transient_error","on_failed","on_bounced","on_suppressed","on_opened","on_clicked","on_unsubscribed","on_complained"],"description":"The specific event that occurred","isRequired":true,"uniqueKey":"data.event","typeLabel":"enum\u003cstring>"},"from":{"type":"string","description":"Sender address. For a campaign message it includes the sender's\nname, as `Name \u003caddress>`.\n","isRequired":true,"uniqueKey":"data.from","typeLabel":"string"},"recipient":{"type":"string","format":"email","description":"Recipient email address","isRequired":true,"uniqueKey":"data.recipient","typeLabel":"string\u003cemail>"},"subject":{"type":"string","description":"Email subject line","isRequired":true,"uniqueKey":"data.subject","typeLabel":"string"},"message_id_header":{"type":"string","description":"Message ID header (same as returned by [Create Message](https://ahasend.com/docs/api-reference/messages/create-message) or [Create Template Message](https://ahasend.com/docs/api-reference/messages/create-template-message))","isRequired":true,"uniqueKey":"data.message_id_header","typeLabel":"string"},"id":{"type":"string","description":"Internal AhaSend message ID","isRequired":true,"uniqueKey":"data.id","typeLabel":"string"},"user_agent":{"type":"string","description":"User agent (only for opened/clicked events)","uniqueKey":"data.user_agent","typeLabel":"string"},"ip":{"type":"string","description":"IP address (only for opened/clicked events)","uniqueKey":"data.ip","typeLabel":"string"},"is_bot":{"type":"boolean","description":"Whether the action was performed by a bot.\n\nBot detection runs on every open and click and always yields a definite\ntrue or false. Current deliveries include the field on every message\nevent; it is meaningful for `message.opened` and always `false`\nelsewhere. Older deliveries may omit it — absence carries no signal, so\ndo not infer `false` from a missing field and never reject a delivery\nbecause of it.\n","uniqueKey":"data.is_bot","typeLabel":"boolean"},"delivery_attempt":{"oneOf":[{"type":"object","description":"Diagnostics for the delivery attempt this event reports on: the\nSMTP status code, the response text, and — on failures — the\nbucket the bounce classifier assigned.\n\nOptional, and absent more often than present. Today it is\n`message.delivered`, `message.bounced`, and\n`message.transient_error` that carry it, and only when an SMTP\nattempt was actually recorded. These are the cases where no attempt\nis recorded, and so no object is sent:\n\n- **Retry exhaustion.** A message that runs out of retries arrives\n as `message.failed`, which reports the exhaustion rather than a\n single attempt.\n- **Out-of-band bounces**, where the DSN arrives separately after\n the destination already accepted the message.\n- **Non-SMTP routing**, where the message was handled outside SMTP.\n Sandbox sends are the exception: they synthesize a representative\n attempt rather than omitting one.\n- **Empty responses**, carrying neither a status code nor any text.\n\nThese cases are not closed, and an explicit `null` means the same\nas a missing field. Always read the object with optional chaining\nand never treat its absence as an error. Equally, do not treat its\npresence on another event sharing this data shape as impossible.\nEvents with their own data shape — `message.clicked`,\n`message.routing`, `suppression.created`, `suppression.deleted`,\n`domain.dns_error`, and the `contact.*` events — never carry one.\n\nOn test webhooks and sandbox deliveries the values are\nrepresentative rather than observed. A sandbox simulation can\nreplace the sample classification with the classification of the\nselected outcome, so it may not agree with the representative SMTP\ncode and response. Do not calibrate a `classification` switch\nagainst sandbox traffic.\n","required":["smtp_code"],"properties":{"smtp_code":{"type":"integer","minimum":0,"description":"SMTP status code recorded for the attempt. Usually this is the code\nreturned by the destination. Always present when this object is\npresent. `0` means AhaSend recorded response content without an SMTP\ncode — an internal error, typically — so do not read `0` as the\nfield being absent.\n","isRequired":true,"uniqueKey":"data.delivery_attempt.oneOf.0.smtp_code","typeLabel":"integer"},"classification":{"type":"string","description":"Bucket the bounce classifier assigned to this attempt. Absent on\nsuccessful deliveries, and absent on a failure the classifier did\nnot label.\n\nKnown values: `InvalidRecipient`, `BadDomain`, `InactiveMailbox`, `InvalidSender`, `QuotaIssues`, `NoAnswerFromHost`, `BadConnection`, `DNSFailure`, `RoutingErrors`, `TransientFailure`, `MessageExpired`, `ProtocolErrors`, `AuthenticationFailed`, `PolicyRelated`, `Uncategorized`.\n\nThis is **not** a closed set. New buckets can be introduced at any\ntime, and this list describes what is emitted today rather than\neverything that may ever appear. Branch on the values you know and\nkeep a fallback branch for everything else; never reject a delivery\nbecause the value is unfamiliar.\n\nNote that `TransientFailure` here is a classification, unrelated to\nthe `message.transient_error` event type or to the `event` field.\n","x-known-values":["InvalidRecipient","BadDomain","InactiveMailbox","InvalidSender","QuotaIssues","NoAnswerFromHost","BadConnection","DNSFailure","RoutingErrors","TransientFailure","MessageExpired","ProtocolErrors","AuthenticationFailed","PolicyRelated","Uncategorized"],"uniqueKey":"data.delivery_attempt.oneOf.0.classification","typeLabel":"string"},"enhanced_status_code":{"type":"string","description":"RFC 3463 enhanced status code in `class.subject.detail` form (for\nexample `5.1.1`), when one was recorded for the attempt.\n","uniqueKey":"data.delivery_attempt.oneOf.0.enhanced_status_code","typeLabel":"string"},"response":{"type":"string","description":"Text describing the outcome, as the MTA recorded it. Present when\nnon-empty.\n\nTwo things it is not. It is not reliably code-free: the reply code\nusually lives in `smtp_code` alone, but some destinations leave the\nreply code, the enhanced code, or both at the front of the text, so\ndo not assume a bare sentence and do not parse codes back out of\nit. And it is not always the destination's own words: when the\nfailure was raised inside AhaSend rather than by the destination,\nthis carries AhaSend's description of that failure instead.\n\nRead it as human-readable diagnostics. Branch on `classification`,\n`smtp_code`, and `enhanced_status_code`.\n","uniqueKey":"data.delivery_attempt.oneOf.0.response","typeLabel":"string"},"description":{"type":"string","description":"Human-readable translation of a complex `response`, present only\nwhen that translation differs from `response` itself.\n\nThis is display prose, not an identifier: its wording changes as\nthe translations improve. Never compare it to a literal and never\nparse it — branch on `classification`, `smtp_code`, or\n`enhanced_status_code` instead.\n","uniqueKey":"data.delivery_attempt.oneOf.0.description","typeLabel":"string"},"command":{"type":"string","description":"Normalized SMTP command name that was in flight when the attempt was\nrecorded (for example `RCPT TO` or `DATA`), when the MTA reported\none. Command arguments such as envelope addresses are not included.\n","uniqueKey":"data.delivery_attempt.oneOf.0.command","typeLabel":"string"}},"uniqueKey":"data.delivery_attempt.oneOf.0","typeLabel":"object"},{"type":"null","description":"Diagnostics for the delivery attempt this event reports on: the\nSMTP status code, the response text, and — on failures — the\nbucket the bounce classifier assigned.\n\nOptional, and absent more often than present. Today it is\n`message.delivered`, `message.bounced`, and\n`message.transient_error` that carry it, and only when an SMTP\nattempt was actually recorded. These are the cases where no attempt\nis recorded, and so no object is sent:\n\n- **Retry exhaustion.** A message that runs out of retries arrives\n as `message.failed`, which reports the exhaustion rather than a\n single attempt.\n- **Out-of-band bounces**, where the DSN arrives separately after\n the destination already accepted the message.\n- **Non-SMTP routing**, where the message was handled outside SMTP.\n Sandbox sends are the exception: they synthesize a representative\n attempt rather than omitting one.\n- **Empty responses**, carrying neither a status code nor any text.\n\nThese cases are not closed, and an explicit `null` means the same\nas a missing field. Always read the object with optional chaining\nand never treat its absence as an error. Equally, do not treat its\npresence on another event sharing this data shape as impossible.\nEvents with their own data shape — `message.clicked`,\n`message.routing`, `suppression.created`, `suppression.deleted`,\n`domain.dns_error`, and the `contact.*` events — never carry one.\n\nOn test webhooks and sandbox deliveries the values are\nrepresentative rather than observed. A sandbox simulation can\nreplace the sample classification with the classification of the\nselected outcome, so it may not agree with the representative SMTP\ncode and response. Do not calibrate a `classification` switch\nagainst sandbox traffic.\n","required":["smtp_code"],"properties":{"classification":{"type":"string","description":"Bucket the bounce classifier assigned to this attempt. Absent on\nsuccessful deliveries, and absent on a failure the classifier did\nnot label.\n\nKnown values: `InvalidRecipient`, `BadDomain`, `InactiveMailbox`, `InvalidSender`, `QuotaIssues`, `NoAnswerFromHost`, `BadConnection`, `DNSFailure`, `RoutingErrors`, `TransientFailure`, `MessageExpired`, `ProtocolErrors`, `AuthenticationFailed`, `PolicyRelated`, `Uncategorized`.\n\nThis is **not** a closed set. New buckets can be introduced at any\ntime, and this list describes what is emitted today rather than\neverything that may ever appear. Branch on the values you know and\nkeep a fallback branch for everything else; never reject a delivery\nbecause the value is unfamiliar.\n\nNote that `TransientFailure` here is a classification, unrelated to\nthe `message.transient_error` event type or to the `event` field.\n","x-known-values":["InvalidRecipient","BadDomain","InactiveMailbox","InvalidSender","QuotaIssues","NoAnswerFromHost","BadConnection","DNSFailure","RoutingErrors","TransientFailure","MessageExpired","ProtocolErrors","AuthenticationFailed","PolicyRelated","Uncategorized"]},"smtp_code":{"type":"integer","minimum":0,"description":"SMTP status code recorded for the attempt. Usually this is the code\nreturned by the destination. Always present when this object is\npresent. `0` means AhaSend recorded response content without an SMTP\ncode — an internal error, typically — so do not read `0` as the\nfield being absent.\n"},"enhanced_status_code":{"type":"string","description":"RFC 3463 enhanced status code in `class.subject.detail` form (for\nexample `5.1.1`), when one was recorded for the attempt.\n"},"response":{"type":"string","description":"Text describing the outcome, as the MTA recorded it. Present when\nnon-empty.\n\nTwo things it is not. It is not reliably code-free: the reply code\nusually lives in `smtp_code` alone, but some destinations leave the\nreply code, the enhanced code, or both at the front of the text, so\ndo not assume a bare sentence and do not parse codes back out of\nit. And it is not always the destination's own words: when the\nfailure was raised inside AhaSend rather than by the destination,\nthis carries AhaSend's description of that failure instead.\n\nRead it as human-readable diagnostics. Branch on `classification`,\n`smtp_code`, and `enhanced_status_code`.\n"},"description":{"type":"string","description":"Human-readable translation of a complex `response`, present only\nwhen that translation differs from `response` itself.\n\nThis is display prose, not an identifier: its wording changes as\nthe translations improve. Never compare it to a literal and never\nparse it — branch on `classification`, `smtp_code`, or\n`enhanced_status_code` instead.\n"},"command":{"type":"string","description":"Normalized SMTP command name that was in flight when the attempt was\nrecorded (for example `RCPT TO` or `DATA`), when the MTA reported\none. Command arguments such as envelope addresses are not included.\n"}},"uniqueKey":"data.delivery_attempt.oneOf.1","typeLabel":"null"}],"uniqueKey":"data.delivery_attempt","typeLabel":"object | null"},"unsubscribe":{"type":"object","required":["method"],"properties":{"method":{"type":"string","enum":["one_click","link"],"description":"`one_click` for a one-click unsubscribe from the recipient's email\nclient (a POST with the body `List-Unsubscribe=One-Click`, RFC\n8058), and `link` for any other unsubscribe.\n","isRequired":true,"uniqueKey":"data.unsubscribe.method","typeLabel":"enum\u003cstring>"}},"description":"How the recipient unsubscribed. Present only on `message.unsubscribed`.","uniqueKey":"data.unsubscribe","typeLabel":"object"},"complaint":{"type":"object","required":["feedback_type","reporter"],"properties":{"feedback_type":{"type":"string","description":"The feedback type of the report (the ARF `Feedback-Type`), in lower\ncase: `abuse` or `fraud`.\n","isRequired":true,"uniqueKey":"data.complaint.feedback_type","typeLabel":"string"},"reporter":{"type":"string","description":"The feedback loop that sent the report. Known values: `yahoo`,\n`microsoft`, and `comcast`.\n\nThis is **not** a closed set: AhaSend can add feedback loops at any\ntime. Keep a fallback branch for an unfamiliar value, and never\nreject a delivery because of it.\n","x-known-values":["yahoo","microsoft","comcast"],"isRequired":true,"uniqueKey":"data.complaint.reporter","typeLabel":"string"}},"description":"The spam complaint report. Present only on `message.complained`.","uniqueKey":"data.complaint","typeLabel":"object"},"campaign_id":{"type":"string","format":"uuid","description":"The campaign that sent the message. Present only on the events of a campaign message.","uniqueKey":"data.campaign_id","typeLabel":"string\u003cuuid>"},"list_id":{"oneOf":[{"type":"string","format":"uuid","description":"The list through which the campaign reached the recipient, or\n`null` when the campaign did not reach the recipient through a\nlist. Present only on the events of a campaign message.\n","uniqueKey":"data.list_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","format":"uuid","description":"The list through which the campaign reached the recipient, or\n`null` when the campaign did not reach the recipient through a\nlist. Present only on the events of a campaign message.\n","uniqueKey":"data.list_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"data.list_id","typeLabel":"string\u003cuuid> | null"},"segment_id":{"oneOf":[{"type":"string","format":"uuid","description":"The segment through which the campaign reached the recipient, or\n`null` when the campaign did not reach the recipient through a\nsegment. Present only on the events of a campaign message.\n","uniqueKey":"data.segment_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","format":"uuid","description":"The segment through which the campaign reached the recipient, or\n`null` when the campaign did not reach the recipient through a\nsegment. Present only on the events of a campaign message.\n","uniqueKey":"data.segment_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"data.segment_id","typeLabel":"string\u003cuuid> | null"}},"isRequired":true,"uniqueKey":"data","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"type":"message.complained","webhook_id":"abe11757-2886-4b55-96f1-0e0afc95795a","timestamp":"2024-05-06T10:30:16.687031577Z","data":{"account_id":"4cdd7bdd-294e-4762-892f-83d40abf5a87","event":"on_complained","from":"Example News \u003cnews@example.com>","recipient":"recipient@example.com","subject":"Our October news","message_id_header":"\u003cmessage-id-12345@localhost>","id":"407926766d2711f09b30960002cafe7c","is_bot":false,"complaint":{"feedback_type":"abuse","reporter":"yahoo"},"campaign_id":"8b0f4c2e-5d1a-4f6b-9c3e-2a7d1e9f0b44","list_id":"c3e1a9d2-7f4b-4e8a-b5c6-1d2e3f4a5b6c","segment_id":null}},"examples":{"Example":{"title":"Example","value":{"type":"message.complained","webhook_id":"abe11757-2886-4b55-96f1-0e0afc95795a","timestamp":"2024-05-06T10:30:16.687031577Z","data":{"account_id":"4cdd7bdd-294e-4762-892f-83d40abf5a87","event":"on_complained","from":"Example News \u003cnews@example.com>","recipient":"recipient@example.com","subject":"Our October news","message_id_header":"\u003cmessage-id-12345@localhost>","id":"407926766d2711f09b30960002cafe7c","is_bot":false,"complaint":{"feedback_type":"abuse","reporter":"yahoo"},"campaign_id":"8b0f4c2e-5d1a-4f6b-9c3e-2a7d1e9f0b44","list_id":"c3e1a9d2-7f4b-4e8a-b5c6-1d2e3f4a5b6c","segment_id":null}}}},"exampleType":"examples"}},"exampleType":"examples"},"responses":{"908a2f93-c538-49a0-a1b6-90378a7fe5a0":{"description":"Webhook received successfully","content":{"_mintlify/placeholder":{"schema":{"type":"object","description":""}}}},"ff83c44d-cae4-496e-9b04-211e5808952f":{"description":"Webhook received successfully","content":{"_mintlify/placeholder":{"schema":{"type":"object","description":""}}}},"5d0d4e6c-6828-4cc1-b2f8-ff639e3a4366":{"description":"Webhook received successfully","content":{"_mintlify/placeholder":{"schema":{"type":"object","description":""}}}},"75842870-5466-4c73-8635-938c1c52ab86":{"description":"Webhook received successfully","content":{"_mintlify/placeholder":{"schema":{"type":"object","description":""}}}}},"security":{},"servers":{"95c7e3b5-e1ae-46d6-9613-a0f4bcec85ed":{"url":"https://your-webhook-endpoint.com","description":"Your webhook endpoint URL (configured in AhaSend dashboard)"}}},"originalFileLocation":"webhooks.yaml"},"subdomain":"ahasend","siteName":"AhaSend","title":"message.complained Webhook Event - AhaSend","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-26T21:02:38.213Z","originalFileLocation":"api-reference/webhooks/message-complained.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"The message.complained webhook fires when a mailbox provider reports an AhaSend campaign email as spam. The payload holds the feedback type and reporter.\">\u003cmeta data-mint-head name=\"application-name\" content=\"AhaSend\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/ahasend/4BjAcdwrGYDKJCaO/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/docs/mintlify-assets/_mintlify/favicons/ahasend/4BjAcdwrGYDKJCaO/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/ahasend/4BjAcdwrGYDKJCaO/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/ahasend/4BjAcdwrGYDKJCaO/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/ahasend/4BjAcdwrGYDKJCaO/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/ahasend/4BjAcdwrGYDKJCaO/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/ahasend/4BjAcdwrGYDKJCaO/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/ahasend/4BjAcdwrGYDKJCaO/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/ahasend/4BjAcdwrGYDKJCaO/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"message.complained Webhook Event - AhaSend\">\u003cmeta data-mint-head property=\"og:description\" content=\"The message.complained webhook fires when a mailbox provider reports an AhaSend campaign email as spam. The payload holds the feedback type and reporter.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"AhaSend\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://ahasend.com/docs/api-reference/webhooks/message-complained\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://ahasend.mintlify.app/_mintlify/api/og/v2?division=Message+Events\u0026amp;title=message.complained+Webhook+Event\u0026amp;description=The+message.complained+webhook+fires+when+a+mailbox+provider+reports+an+AhaSend+campaign+email+as+spam.+The+payload+holds+the+feedback+type+and+reporter.\u0026amp;theme=fec911c84bb9f722051c4af3\u0026amp;signature=705bb0d504882cfd9c30ccb5446ee8c64952a160c44ca27dcc69ccff2c789291\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"message.complained Webhook Event - AhaSend\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"The message.complained webhook fires when a mailbox provider reports an AhaSend campaign email as spam. The payload holds the feedback type and reporter.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://ahasend.mintlify.app/_mintlify/api/og/v2?division=Message+Events\u0026amp;title=message.complained+Webhook+Event\u0026amp;description=The+message.complained+webhook+fires+when+a+mailbox+provider+reports+an+AhaSend+campaign+email+as+spam.+The+payload+holds+the+feedback+type+and+reporter.\u0026amp;theme=fec911c84bb9f722051c4af3\u0026amp;signature=705bb0d504882cfd9c30ccb5446ee8c64952a160c44ca27dcc69ccff2c789291\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/docs/mintlify-assets/_mintlify/favicons/ahasend/4BjAcdwrGYDKJCaO/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"AhaSend\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#066fd1\">\u003clink data-mint-head rel=\"canonical\" href=\"https://ahasend.com/docs/api-reference/webhooks/message-complained\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/docs/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/docs/api-reference/webhooks/message-complained.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://ahasend.com/#organization\",\"name\":\"AhaSend\",\"legalName\":\"AhaSend B.V.\",\"url\":\"https://ahasend.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/ahasend/F35Ozd-1GsftDpcH/logo.png?fit=max\u0026auto=format\u0026n=F35Ozd-1GsftDpcH\u0026q=85\u0026s=ca1d4c27f7c2811598e65cb25a21323c\"},\"sameAs\":[\"https://x.com/aha_send\",\"https://www.linkedin.com/company/ahasend\",\"https://github.com/ahasend\"]},{\"@type\":\"WebSite\",\"@id\":\"https://ahasend.com/docs#website\",\"name\":\"AhaSend\",\"url\":\"https://ahasend.com/docs\",\"publisher\":{\"@id\":\"https://ahasend.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://ahasend.com/docs/api-reference/webhooks/message-complained#webpage\",\"url\":\"https://ahasend.com/docs/api-reference/webhooks/message-complained\",\"name\":\"message.complained Webhook Event\",\"description\":\"The message.complained webhook fires when a mailbox provider reports an AhaSend campaign email as spam. The payload holds the feedback type and reporter.\",\"dateModified\":\"2026-10-26T21:02:38.213Z\",\"isPartOf\":{\"@id\":\"https://ahasend.com/docs#website\"},\"breadcrumb\":{\"@id\":\"https://ahasend.com/docs/api-reference/webhooks/message-complained#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://ahasend.com/docs/api-reference/webhooks/message-complained#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Webhooks\",\"item\":\"https://ahasend.com/docs/api-reference/webhooks/index\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Message Events\",\"item\":\"https://ahasend.com/docs/api-reference/webhooks/message-reception\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"message.complained Webhook Event\",\"item\":\"https://ahasend.com/docs/api-reference/webhooks/message-complained\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://ahasend.com/docs/api-reference/webhooks/message-complained#apireference\",\"headline\":\"message.complained Webhook Event\",\"name\":\"message.complained Webhook Event\",\"description\":\"The message.complained webhook fires when a mailbox provider reports an AhaSend campaign email as spam. The payload holds the feedback type and reporter.\",\"url\":\"https://ahasend.com/docs/api-reference/webhooks/message-complained\",\"mainEntityOfPage\":{\"@id\":\"https://ahasend.com/docs/api-reference/webhooks/message-complained#webpage\"},\"dateModified\":\"2026-10-26T21:02:38.213Z\",\"publisher\":{\"@id\":\"https://ahasend.com/#organization\"},\"isPartOf\":{\"@id\":\"https://ahasend.com/docs#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"AhaSend\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"AhaSend","nav":{"global":null,"tabs":[{"tab":"Documentation","icon":"book-open","pages":[{"title":"Documentation","href":""}]},{"tab":"API Reference","icon":"code","groups":[{"group":"Overview","pages":[{"title":"Email API Reference (v2)","sidebarTitle":"Introduction","icon":"book","href":"/api-reference"},{"title":"API Authentication with Bearer API Keys","sidebarTitle":"Authentication","icon":"key","href":"/api-reference/authentication"},{"title":"API Key Scopes and Permissions","sidebarTitle":"Scopes","icon":"lock","href":"/api-reference/scopes"},{"title":"API Rate Limits and 429 Handling","sidebarTitle":"Rate Limits","icon":"gauge-high","href":"/api-reference/rate-limits"},{"title":"Idempotency Keys for Safe API Retries","icon":"repeat","sidebarTitle":"Idempotency","href":"/api-reference/idempotency"},{"title":"API Error Codes and Error Responses","icon":"triangle-exclamation","sidebarTitle":"Errors","href":"/api-reference/errors"}]},{"group":"API reference","pages":[{"group":"Messages","icon":"envelope","pages":[{"title":"Send an Email via the API","sidebarTitle":"Create Message","openapi":"openapi.yaml POST /v2/accounts/{account_id}/messages","href":"/api-reference/messages/create-message"},{"title":"Send a Transactional Template via the API","sidebarTitle":"Create Template Message","openapi":"openapi.yaml POST /v2/accounts/{account_id}/messages/template","href":"/api-reference/messages/create-template-message"},{"title":"Send Email with CC and BCC via the API","sidebarTitle":"Create Conversation","openapi":"openapi.yaml POST /v2/accounts/{account_id}/messages/conversation","href":"/api-reference/messages/create-conversation"},{"title":"Get a Message by ID via the API","sidebarTitle":"Get Message","openapi":"openapi.yaml GET /v2/accounts/{account_id}/messages/{message_id}","href":"/api-reference/messages/get-message"},{"title":"List and Search Sent Emails via the API","sidebarTitle":"List Messages","openapi":"openapi.yaml GET /v2/accounts/{account_id}/messages","href":"/api-reference/messages/get-messages"},{"title":"Cancel a Scheduled Email via the API","sidebarTitle":"Cancel Message","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/messages/{message_id}/cancel","href":"/api-reference/messages/cancel-message"}]},{"group":"Transactional Templates","icon":"file-lines","pages":[{"title":"Create a Transactional Template via the API","sidebarTitle":"Create Template","openapi":"openapi.yaml POST /v2/accounts/{account_id}/templates","href":"/api-reference/templates/create-template"},{"title":"Get a Transactional Template via the API","sidebarTitle":"Get Template","openapi":"openapi.yaml GET /v2/accounts/{account_id}/templates/{template_id}","href":"/api-reference/templates/get-template"},{"title":"Get a Published Transactional Template via the API","sidebarTitle":"Get Published Template","openapi":"openapi.yaml GET /v2/accounts/{account_id}/templates/{template_id}/published","href":"/api-reference/templates/get-published-template"},{"title":"List Transactional Templates via the API","sidebarTitle":"List Templates","openapi":"openapi.yaml GET /v2/accounts/{account_id}/templates","href":"/api-reference/templates/get-templates"},{"title":"Update a Transactional Template via the API","sidebarTitle":"Update Template","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/templates/{template_id}","href":"/api-reference/templates/update-template"},{"title":"Publish a Template Draft via the API","sidebarTitle":"Publish Template","openapi":"openapi.yaml POST /v2/accounts/{account_id}/templates/{template_id}/publish","href":"/api-reference/templates/publish-template"},{"title":"Discard a Template Draft via the API","sidebarTitle":"Discard Template Draft","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/templates/{template_id}/draft","href":"/api-reference/templates/discard-template-draft"},{"title":"List Template Versions via the API","sidebarTitle":"List Template Versions","openapi":"openapi.yaml GET /v2/accounts/{account_id}/templates/{template_id}/versions","href":"/api-reference/templates/get-template-versions"},{"title":"Get a Template Version via the API","sidebarTitle":"Get Template Version","openapi":"openapi.yaml GET /v2/accounts/{account_id}/templates/{template_id}/versions/{version_id}","href":"/api-reference/templates/get-template-version"},{"title":"Restore a Template Version via the API","sidebarTitle":"Restore Template Version","openapi":"openapi.yaml POST /v2/accounts/{account_id}/templates/{template_id}/versions/{version_id}/restore","href":"/api-reference/templates/restore-template-version"},{"title":"Delete a Transactional Template via the API","sidebarTitle":"Delete Template","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/templates/{template_id}","href":"/api-reference/templates/delete-template"}]},{"group":"Campaigns","icon":"bullhorn","pages":[{"title":"Campaigns API Overview","sidebarTitle":"Introduction","icon":"bullhorn","href":"/api-reference/campaigns/overview"},{"title":"Create a Campaign via the API","sidebarTitle":"Create Campaign","openapi":"openapi.yaml POST /v2/accounts/{account_id}/campaigns","href":"/api-reference/campaigns/create-campaign"},{"title":"Get a Campaign via the API","sidebarTitle":"Get Campaign","openapi":"openapi.yaml GET /v2/accounts/{account_id}/campaigns/{campaign_id}","href":"/api-reference/campaigns/get-campaign"},{"title":"List Campaigns via the API","sidebarTitle":"List Campaigns","openapi":"openapi.yaml GET /v2/accounts/{account_id}/campaigns","href":"/api-reference/campaigns/get-campaigns"},{"title":"Update a Campaign via the API","sidebarTitle":"Update Campaign","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/campaigns/{campaign_id}","href":"/api-reference/campaigns/update-campaign"},{"title":"Duplicate a Campaign via the API","sidebarTitle":"Duplicate Campaign","openapi":"openapi.yaml POST /v2/accounts/{account_id}/campaigns/{campaign_id}/duplicate","href":"/api-reference/campaigns/duplicate-campaign"},{"title":"Send a Campaign Test via the API","sidebarTitle":"Test Campaign","openapi":"openapi.yaml POST /v2/accounts/{account_id}/campaigns/{campaign_id}/test","href":"/api-reference/campaigns/test-campaign"},{"title":"Send or Schedule a Campaign via the API","sidebarTitle":"Send Campaign","openapi":"openapi.yaml POST /v2/accounts/{account_id}/campaigns/{campaign_id}/send","href":"/api-reference/campaigns/send-campaign"},{"title":"Unschedule a Campaign via the API","sidebarTitle":"Unschedule Campaign","openapi":"openapi.yaml POST /v2/accounts/{account_id}/campaigns/{campaign_id}/unschedule","href":"/api-reference/campaigns/unschedule-campaign"},{"title":"Get Campaign Stats via the API","sidebarTitle":"Get Campaign Stats","openapi":"openapi.yaml GET /v2/accounts/{account_id}/campaigns/{campaign_id}/stats","href":"/api-reference/campaigns/get-campaign-stats"},{"title":"List Campaign Recipients via the API","sidebarTitle":"List Campaign Recipients","openapi":"openapi.yaml GET /v2/accounts/{account_id}/campaigns/{campaign_id}/recipients","href":"/api-reference/campaigns/get-campaign-recipients"},{"title":"Delete a Campaign via the API","sidebarTitle":"Delete Campaign","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/campaigns/{campaign_id}","href":"/api-reference/campaigns/delete-campaign"}]},{"group":"Campaign Templates","icon":"palette","pages":[{"title":"Create a Campaign Template via the API","sidebarTitle":"Create Template","openapi":"openapi.yaml POST /v2/accounts/{account_id}/campaign-templates","href":"/api-reference/campaign-templates/create-campaign-template"},{"title":"Get a Campaign Template via the API","sidebarTitle":"Get Template","openapi":"openapi.yaml GET /v2/accounts/{account_id}/campaign-templates/{template_id}","href":"/api-reference/campaign-templates/get-campaign-template"},{"title":"List Campaign Templates via the API","sidebarTitle":"List Templates","openapi":"openapi.yaml GET /v2/accounts/{account_id}/campaign-templates","href":"/api-reference/campaign-templates/get-campaign-templates"},{"title":"Update a Campaign Template via the API","sidebarTitle":"Update Template","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/campaign-templates/{template_id}","href":"/api-reference/campaign-templates/update-campaign-template"},{"title":"Delete a Campaign Template via the API","sidebarTitle":"Delete Template","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/campaign-templates/{template_id}","href":"/api-reference/campaign-templates/delete-campaign-template"}]},{"group":"Contacts","icon":"address-book","pages":[{"title":"Contacts API Overview","sidebarTitle":"Introduction","icon":"address-book","href":"/api-reference/contacts/overview"},{"title":"Create a Contact via the API","sidebarTitle":"Create Contact","openapi":"openapi.yaml POST /v2/accounts/{account_id}/contacts","href":"/api-reference/contacts/create-contact"},{"title":"Get a Contact via the API","sidebarTitle":"Get Contact","openapi":"openapi.yaml GET /v2/accounts/{account_id}/contacts/{id_or_email}","href":"/api-reference/contacts/get-contact"},{"title":"List Contacts via the API","sidebarTitle":"List Contacts","openapi":"openapi.yaml GET /v2/accounts/{account_id}/contacts","href":"/api-reference/contacts/get-contacts"},{"title":"Update a Contact via the API","sidebarTitle":"Update Contact","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/contacts/{id_or_email}","href":"/api-reference/contacts/update-contact"},{"title":"Delete a Contact via the API","sidebarTitle":"Delete Contact","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/contacts/{id_or_email}","href":"/api-reference/contacts/delete-contact"},{"title":"Create or Update Contacts in a Batch via the API","sidebarTitle":"Batch Upsert Contacts","openapi":"openapi.yaml POST /v2/accounts/{account_id}/contacts/batch","href":"/api-reference/contacts/batch-upsert-contacts"}]},{"group":"Lists","icon":"list-ul","pages":[{"title":"Lists API Overview","sidebarTitle":"Introduction","icon":"list-ul","href":"/api-reference/lists/overview"},{"title":"Create a List via the API","sidebarTitle":"Create List","openapi":"openapi.yaml POST /v2/accounts/{account_id}/lists","href":"/api-reference/lists/create-list"},{"title":"Get a List via the API","sidebarTitle":"Get List","openapi":"openapi.yaml GET /v2/accounts/{account_id}/lists/{list_id}","href":"/api-reference/lists/get-list"},{"title":"List Contact Lists via the API","sidebarTitle":"List Lists","openapi":"openapi.yaml GET /v2/accounts/{account_id}/lists","href":"/api-reference/lists/get-lists"},{"title":"Update a List via the API","sidebarTitle":"Update List","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/lists/{list_id}","href":"/api-reference/lists/update-list"},{"title":"Delete a List via the API","sidebarTitle":"Delete List","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/lists/{list_id}","href":"/api-reference/lists/delete-list"},{"title":"List the Contacts on a List via the API","sidebarTitle":"List Contacts on a List","openapi":"openapi.yaml GET /v2/accounts/{account_id}/lists/{list_id}/contacts","href":"/api-reference/lists/get-list-contacts"},{"title":"Add or Update a List Contact via the API","sidebarTitle":"Add or Update List Contact","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/lists/{list_id}/contacts/{id_or_email}","href":"/api-reference/lists/upsert-list-contact"},{"title":"Add Contacts to a List in a Batch via the API","sidebarTitle":"Batch Add List Contacts","openapi":"openapi.yaml POST /v2/accounts/{account_id}/lists/{list_id}/contacts/batch","href":"/api-reference/lists/batch-add-list-contacts"},{"title":"Remove a Contact from a List via the API","sidebarTitle":"Remove List Contact","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/lists/{list_id}/contacts/{id_or_email}","href":"/api-reference/lists/delete-list-contact"},{"title":"List a Contact's Lists via the API","sidebarTitle":"List Contact's Lists","openapi":"openapi.yaml GET /v2/accounts/{account_id}/contacts/{id_or_email}/lists","href":"/api-reference/lists/get-contact-lists"}]},{"group":"Segments","icon":"filter","pages":[{"title":"Segments API Overview","sidebarTitle":"Introduction","icon":"filter","href":"/api-reference/segments/overview"},{"title":"Preview a Segment via the API","sidebarTitle":"Preview Segment","openapi":"openapi.yaml POST /v2/accounts/{account_id}/segments/preview","href":"/api-reference/segments/preview-segment"},{"title":"Create a Segment via the API","sidebarTitle":"Create Segment","openapi":"openapi.yaml POST /v2/accounts/{account_id}/segments","href":"/api-reference/segments/create-segment"},{"title":"Get a Segment via the API","sidebarTitle":"Get Segment","openapi":"openapi.yaml GET /v2/accounts/{account_id}/segments/{segment_id}","href":"/api-reference/segments/get-segment"},{"title":"List Segments via the API","sidebarTitle":"List Segments","openapi":"openapi.yaml GET /v2/accounts/{account_id}/segments","href":"/api-reference/segments/get-segments"},{"title":"Update a Segment via the API","sidebarTitle":"Update Segment","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/segments/{segment_id}","href":"/api-reference/segments/update-segment"},{"title":"Delete a Segment via the API","sidebarTitle":"Delete Segment","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/segments/{segment_id}","href":"/api-reference/segments/delete-segment"},{"title":"List the Contacts in a Segment via the API","sidebarTitle":"List Segment Contacts","openapi":"openapi.yaml GET /v2/accounts/{account_id}/segments/{segment_id}/contacts","href":"/api-reference/segments/get-segment-contacts"},{"title":"List a Contact's Segments via the API","sidebarTitle":"List Contact's Segments","openapi":"openapi.yaml GET /v2/accounts/{account_id}/contacts/{id_or_email}/segments","href":"/api-reference/segments/get-contact-segments"}]},{"group":"Suppressions","icon":"ban","pages":[{"title":"Add an Address to the Suppression List via the API","sidebarTitle":"Create Suppression","openapi":"openapi.yaml POST /v2/accounts/{account_id}/suppressions","href":"/api-reference/suppressions/create-suppression"},{"title":"List Suppressed Addresses via the API","sidebarTitle":"List Suppressions","openapi":"openapi.yaml GET /v2/accounts/{account_id}/suppressions","href":"/api-reference/suppressions/get-suppressions"},{"title":"Remove a Suppression via the API","sidebarTitle":"Delete Suppression","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/suppressions","href":"/api-reference/suppressions/delete-suppression"},{"title":"Delete All Suppressions via the API","sidebarTitle":"Delete All Suppressions","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/suppressions/all","href":"/api-reference/suppressions/wipe-suppressions"}]},{"group":"SMTP Credentials","icon":"user-shield","pages":[{"title":"Create SMTP Credentials via the API","sidebarTitle":"Create SMTP Credential","openapi":"openapi.yaml POST /v2/accounts/{account_id}/smtp-credentials","href":"/api-reference/smtp-credentials/create-smtp-credential"},{"title":"Get an SMTP Credential via the API","sidebarTitle":"Get SMTP Credential","openapi":"openapi.yaml GET /v2/accounts/{account_id}/smtp-credentials/{smtp_credential_id}","href":"/api-reference/smtp-credentials/get-smtp-credential"},{"title":"List SMTP Credentials via the API","sidebarTitle":"List SMTP Credentials","openapi":"openapi.yaml GET /v2/accounts/{account_id}/smtp-credentials","href":"/api-reference/smtp-credentials/get-smtp-credentials"},{"title":"Delete an SMTP Credential via the API","sidebarTitle":"Delete SMTP Credential","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/smtp-credentials/{smtp_credential_id}","href":"/api-reference/smtp-credentials/delete-smtp-credential"}]},{"group":"Webhooks","icon":"webhook","pages":[{"title":"Create a Webhook via the API","sidebarTitle":"Create Webhook","openapi":"openapi.yaml POST /v2/accounts/{account_id}/webhooks","href":"/api-reference/webhooks/create-webhook"},{"title":"Get a Webhook via the API","sidebarTitle":"Get Webhook","openapi":"openapi.yaml GET /v2/accounts/{account_id}/webhooks/{webhook_id}","href":"/api-reference/webhooks/get-webhook"},{"title":"List Webhooks via the API","sidebarTitle":"List Webhooks","openapi":"openapi.yaml GET /v2/accounts/{account_id}/webhooks","href":"/api-reference/webhooks/get-webhooks"},{"title":"Update a Webhook via the API","sidebarTitle":"Update Webhook","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/webhooks/{webhook_id}","href":"/api-reference/webhooks/update-webhook"},{"title":"Delete a Webhook via the API","sidebarTitle":"Delete Webhook","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/webhooks/{webhook_id}","href":"/api-reference/webhooks/delete-webhook"}]},{"group":"Routes","icon":"route","pages":[{"title":"Create an Inbound Email Route via the API","sidebarTitle":"Create Route","openapi":"openapi.yaml POST /v2/accounts/{account_id}/routes","href":"/api-reference/routes/create-route"},{"title":"Get an Inbound Email Route via the API","sidebarTitle":"Get Route","openapi":"openapi.yaml GET /v2/accounts/{account_id}/routes/{route_id}","href":"/api-reference/routes/get-route"},{"title":"List Inbound Email Routes via the API","sidebarTitle":"List Routes","openapi":"openapi.yaml GET /v2/accounts/{account_id}/routes","href":"/api-reference/routes/get-routes"},{"title":"Update an Inbound Email Route via the API","sidebarTitle":"Update Route","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/routes/{route_id}","href":"/api-reference/routes/update-route"},{"title":"Delete an Inbound Email Route via the API","sidebarTitle":"Delete Route","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/routes/{route_id}","href":"/api-reference/routes/delete-route"}]},{"group":"Domains","icon":"globe","pages":[{"title":"Add a Sending Domain via the API","sidebarTitle":"Create Domain","openapi":"openapi.yaml POST /v2/accounts/{account_id}/domains","href":"/api-reference/domains/create-domain"},{"title":"Get a Domain and Its DNS Records via the API","sidebarTitle":"Get Domain","openapi":"openapi.yaml GET /v2/accounts/{account_id}/domains/{domain}","href":"/api-reference/domains/get-domain"},{"title":"List Sending Domains via the API","sidebarTitle":"List Domains","openapi":"openapi.yaml GET /v2/accounts/{account_id}/domains","href":"/api-reference/domains/get-domains"},{"title":"Update a Sending Domain via the API","sidebarTitle":"Update Domain","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/domains/{domain}","href":"/api-reference/domains/update-domain"},{"title":"Check Domain DNS Records via the API","sidebarTitle":"Check Domain DNS","openapi":"openapi.yaml POST /v2/accounts/{account_id}/domains/{domain}/check-dns","href":"/api-reference/domains/check-dns"},{"title":"Delete a Sending Domain via the API","sidebarTitle":"Delete Domain","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/domains/{domain}","href":"/api-reference/domains/delete-domain"}]},{"group":"Accounts","icon":"building","pages":[{"title":"Get Account Details via the API","sidebarTitle":"Get Account","openapi":"openapi.yaml GET /v2/accounts/{account_id}","href":"/api-reference/accounts/get-account"},{"title":"Update Account Settings via the API","sidebarTitle":"Update Account","openapi":"openapi.yaml PUT /v2/accounts/{account_id}","href":"/api-reference/accounts/update-account"},{"title":"List Account Members via the API","sidebarTitle":"List Account Members","openapi":"openapi.yaml GET /v2/accounts/{account_id}/members","href":"/api-reference/accounts/get-account-members"},{"title":"Add an Account Member via the API","sidebarTitle":"Add Account Member","openapi":"openapi.yaml POST /v2/accounts/{account_id}/members","href":"/api-reference/accounts/create-account-member"},{"title":"Remove an Account Member via the API","sidebarTitle":"Remove Account Member","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/members/{user_id}","href":"/api-reference/accounts/delete-account-member"}]},{"group":"Sub-Accounts","icon":"sitemap","pages":[{"title":"Sub-Accounts API Overview","sidebarTitle":"Introduction","icon":"sitemap","href":"/api-reference/sub-accounts/overview"},{"title":"Create a Sub-Account via the API","sidebarTitle":"Create Sub-Account","openapi":"openapi.yaml POST /v2/accounts/{account_id}/sub-accounts","href":"/api-reference/sub-accounts/create-sub-account"},{"title":"List Sub-Accounts via the API","sidebarTitle":"List Sub-Accounts","openapi":"openapi.yaml GET /v2/accounts/{account_id}/sub-accounts","href":"/api-reference/sub-accounts/get-sub-accounts"},{"title":"Get a Sub-Account via the API","sidebarTitle":"Get Sub-Account","openapi":"openapi.yaml GET /v2/accounts/{account_id}/sub-accounts/{sub_account_id}","href":"/api-reference/sub-accounts/get-sub-account"},{"title":"Update a Sub-Account via the API","sidebarTitle":"Update Sub-Account","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/sub-accounts/{sub_account_id}","href":"/api-reference/sub-accounts/update-sub-account"},{"title":"Pause a Sub-Account via the API","sidebarTitle":"Pause Sub-Account","openapi":"openapi.yaml POST /v2/accounts/{account_id}/sub-accounts/{sub_account_id}/suspend","href":"/api-reference/sub-accounts/suspend-sub-account"},{"title":"Resume a Sub-Account via the API","sidebarTitle":"Resume Sub-Account","openapi":"openapi.yaml POST /v2/accounts/{account_id}/sub-accounts/{sub_account_id}/unsuspend","href":"/api-reference/sub-accounts/unsuspend-sub-account"},{"title":"Unpause a Sub-Account Domain via the API","sidebarTitle":"Unpause Sub-Account Domain","openapi":"openapi.yaml POST /v2/accounts/{account_id}/sub-accounts/{sub_account_id}/domains/{domain}/unpause","href":"/api-reference/sub-accounts/unpause-sub-account-domain"},{"title":"Delete a Sub-Account via the API","sidebarTitle":"Delete Sub-Account","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/sub-accounts/{sub_account_id}","href":"/api-reference/sub-accounts/delete-sub-account"},{"title":"Get Sub-Account Usage via the API","sidebarTitle":"Sub-Account Usage","openapi":"openapi.yaml GET /v2/accounts/{account_id}/sub-accounts/usage","href":"/api-reference/sub-accounts/get-sub-accounts-usage"}]},{"group":"Sub-Account API Keys","icon":"key","pages":[{"title":"Create a Sub-Account API Key via the API","sidebarTitle":"Create API Key","openapi":"openapi.yaml POST /v2/accounts/{account_id}/sub-accounts/{sub_account_id}/api-keys","href":"/api-reference/sub-accounts/create-sub-account-api-key"},{"title":"Get a Sub-Account API Key via the API","sidebarTitle":"Get API Key","openapi":"openapi.yaml GET /v2/accounts/{account_id}/sub-accounts/{sub_account_id}/api-keys/{key_id}","href":"/api-reference/sub-accounts/get-sub-account-api-key"},{"title":"List Sub-Account API Keys via the API","sidebarTitle":"List API Keys","openapi":"openapi.yaml GET /v2/accounts/{account_id}/sub-accounts/{sub_account_id}/api-keys","href":"/api-reference/sub-accounts/get-sub-account-api-keys"},{"title":"Update a Sub-Account API Key via the API","sidebarTitle":"Update API Key","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/sub-accounts/{sub_account_id}/api-keys/{key_id}","href":"/api-reference/sub-accounts/update-sub-account-api-key"},{"title":"Delete a Sub-Account API Key via the API","sidebarTitle":"Delete API Key","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/sub-accounts/{sub_account_id}/api-keys/{key_id}","href":"/api-reference/sub-accounts/delete-sub-account-api-key"}]},{"group":"Reports","icon":"chart-line","pages":[{"title":"Get Email Deliverability Statistics via the API","sidebarTitle":"Deliverability Report","openapi":"openapi.yaml GET /v2/accounts/{account_id}/statistics/transactional/deliverability","href":"/api-reference/reports/get-deliverability-report"},{"title":"Get Email Bounce Statistics via the API","sidebarTitle":"Bounce Report","openapi":"openapi.yaml GET /v2/accounts/{account_id}/statistics/transactional/bounce","href":"/api-reference/reports/get-bounce-report"},{"title":"Get Email Delivery Time Statistics via the API","sidebarTitle":"Delivery Time Report","openapi":"openapi.yaml GET /v2/accounts/{account_id}/statistics/transactional/delivery-time","href":"/api-reference/reports/get-delivery-time-report"}]},{"group":"API Keys","icon":"key","pages":[{"title":"Create an API Key via the API","sidebarTitle":"Create API Key","openapi":"openapi.yaml POST /v2/accounts/{account_id}/api-keys","href":"/api-reference/api-keys/create-api-key"},{"title":"Get an API Key via the API","sidebarTitle":"Get API Key","openapi":"openapi.yaml GET /v2/accounts/{account_id}/api-keys/{key_id}","href":"/api-reference/api-keys/get-api-key"},{"title":"List API Keys via the API","sidebarTitle":"List API Keys","openapi":"openapi.yaml GET /v2/accounts/{account_id}/api-keys","href":"/api-reference/api-keys/get-api-keys"},{"title":"Update an API Key via the API","sidebarTitle":"Update API Key","openapi":"openapi.yaml PUT /v2/accounts/{account_id}/api-keys/{key_id}","href":"/api-reference/api-keys/update-api-key"},{"title":"Delete an API Key via the API","sidebarTitle":"Delete API Key","openapi":"openapi.yaml DELETE /v2/accounts/{account_id}/api-keys/{key_id}","href":"/api-reference/api-keys/delete-api-key"}]},{"group":"Utility endpoints","icon":"bolt","pages":[{"title":"Test Your API Key with the Ping Endpoint","sidebarTitle":"Ping","openapi":"openapi.yaml GET /v2/ping","href":"/api-reference/utility/ping"}]}]},{"group":"Webhooks","pages":[{"title":"Webhook Events and Payload Reference","sidebarTitle":"Introduction","icon":"webhook","href":"/api-reference/webhooks/index"},{"title":"Verify Webhook and Route Signatures (HMAC)","sidebarTitle":"Security","icon":"shield-check","href":"/api-reference/webhooks/security"},{"title":"Webhook and Route Retry Policy","sidebarTitle":"Retry Policy","icon":"repeat","href":"/api-reference/webhooks/retry-policy"},{"group":"Message Events","icon":"envelope","pages":[{"title":"message.reception Webhook Event","sidebarTitle":"Reception","openapi":"webhooks.yaml webhook message.reception","href":"/api-reference/webhooks/message-reception"},{"title":"message.delivered Webhook Event","sidebarTitle":"Delivered","openapi":"webhooks.yaml webhook message.delivered","href":"/api-reference/webhooks/message-delivered"},{"title":"message.transient_error (Deferred) Webhook Event","sidebarTitle":"Deferred","openapi":"webhooks.yaml webhook message.transient_error","href":"/api-reference/webhooks/message-transient_error"},{"title":"message.failed Webhook Event","sidebarTitle":"Failed","openapi":"webhooks.yaml webhook message.failed","href":"/api-reference/webhooks/message-failed"},{"title":"message.bounced Webhook Event","sidebarTitle":"Bounced","openapi":"webhooks.yaml webhook message.bounced","href":"/api-reference/webhooks/message-bounced"},{"title":"message.suppressed Webhook Event","sidebarTitle":"Suppressed","openapi":"webhooks.yaml webhook message.suppressed","href":"/api-reference/webhooks/message-suppressed"},{"title":"message.opened Webhook Event","sidebarTitle":"Opened","openapi":"webhooks.yaml webhook message.opened","href":"/api-reference/webhooks/message-opened"},{"title":"message.clicked Webhook Event","sidebarTitle":"Clicked","openapi":"webhooks.yaml webhook message.clicked","href":"/api-reference/webhooks/message-clicked"},{"title":"message.unsubscribed Webhook Event","sidebarTitle":"Unsubscribed","openapi":"webhooks.yaml webhook message.unsubscribed","description":"The message.unsubscribed webhook fires when a recipient unsubscribes from an AhaSend campaign email through its link or one-click unsubscribe. Payload.","href":"/api-reference/webhooks/message-unsubscribed"},{"title":"message.complained Webhook Event","sidebarTitle":"Complained","openapi":"webhooks.yaml webhook message.complained","href":"/api-reference/webhooks/message-complained"}]},{"group":"Suppression Events","icon":"ban","pages":[{"title":"suppression.created Webhook Event","sidebarTitle":"Suppression Created","openapi":"webhooks.yaml webhook suppression.created","description":"The suppression.created webhook fires when AhaSend suppresses an address, for example after a hard bounce, or when a suppression gets a new reason.","href":"/api-reference/webhooks/suppression-created"},{"title":"suppression.deleted Webhook Event","sidebarTitle":"Suppression Deleted","openapi":"webhooks.yaml webhook suppression.deleted","href":"/api-reference/webhooks/suppression-deleted"}]},{"group":"Domain Events","icon":"globe","pages":[{"title":"domain.dns_error Webhook Event","sidebarTitle":"DNS Error","openapi":"webhooks.yaml webhook domain.dns_error","href":"/api-reference/webhooks/domain-dns_error"}]},{"group":"Contact Events","icon":"address-book","pages":[{"title":"contact.created Webhook Event","sidebarTitle":"Contact Created","openapi":"webhooks.yaml webhook contact.created","href":"/api-reference/webhooks/contact-created"},{"title":"contact.updated Webhook Event","sidebarTitle":"Contact Updated","openapi":"webhooks.yaml webhook contact.updated","href":"/api-reference/webhooks/contact-updated"},{"title":"contact.deleted Webhook Event","sidebarTitle":"Contact Deleted","openapi":"webhooks.yaml webhook contact.deleted","href":"/api-reference/webhooks/contact-deleted"},{"title":"contact.added_to_list Webhook Event","sidebarTitle":"Contact Added to List","openapi":"webhooks.yaml webhook contact.added_to_list","href":"/api-reference/webhooks/contact-added_to_list"},{"title":"contact.removed_from_list Webhook Event","sidebarTitle":"Contact Removed from List","openapi":"webhooks.yaml webhook contact.removed_from_list","href":"/api-reference/webhooks/contact-removed_from_list"},{"title":"contact.subscribed Webhook Event","sidebarTitle":"Contact Subscribed","openapi":"webhooks.yaml webhook contact.subscribed","href":"/api-reference/webhooks/contact-subscribed"},{"title":"contact.unsubscribed Webhook Event","sidebarTitle":"Contact Unsubscribed","openapi":"webhooks.yaml webhook contact.unsubscribed","href":"/api-reference/webhooks/contact-unsubscribed"},{"title":"contact.complained Webhook Event","sidebarTitle":"Contact Complained","openapi":"webhooks.yaml webhook contact.complained","href":"/api-reference/webhooks/contact-complained"}]}]},{"group":"Message Routing","pages":[{"title":"Inbound Email Routing API Overview","sidebarTitle":"Introduction","icon":"route","href":"/api-reference/routes/index"},{"title":"message.routing Inbound Email Webhook Event","sidebarTitle":"Message Routing","openapi":"webhooks.yaml webhook message.routing","href":"/api-reference/routes/route-message"}]},{"group":"API v1 (legacy)","pages":[{"title":"API v1 vs v2: Differences and Migration","sidebarTitle":"v1 vs v2","icon":"code-compare","href":"/api-reference/v1/v1-vs-v2"},{"title":"Send Email with API v1 (Legacy)","sidebarTitle":"Send Email (Legacy)","icon":"paper-plane","openapi":"openapi-v1.yaml POST /v1/email/send","href":"/api-reference/v1/index"}]}]},{"tab":"CLI","icon":"square-terminal","pages":[{"title":"CLI","href":"/cli"}]},{"tab":"Guides","icon":"plug","pages":[{"title":"Guides","href":"/guides"}]},{"tab":"Changelog","icon":"clock-rotate-left","pages":[{"title":"Changelog","href":"/changelog"}]},{"tab":"Roadmap","icon":"map","pages":[{"title":"Roadmap","href":"/roadmap"}]}]},"title":"message.complained Webhook Event - AhaSend","buildId":"dpl_GvhK4qVXq51DpfYJLCtPpYNN4YHN","deploymentId":"dpl_GvhK4qVXq51DpfYJLCtPpYNN4YHN","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-Bg4Z7D_G.js","utils-Biz734EK.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-C6F9YHs6.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-BoJjY_VP.js","snippetPresets-CnZ-mOFh.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-DC_SB2pp.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-BYKtOiIP.js","shallow-COAac_UD.js","getApiPlaygroundDisplay-BV4Viqi2.js","CodeSnippet-DDgW-JXl.js","CodeSnippets-CP1LpNhG.js","Page-BeiUfucV.js","getPastedJson-Cvgvbfmv.js","icon-D-H368xH.js","MethodPill-CXSxH1VW.js","DuplicateIcon-JcbBzF1x.js","createIcon-BDt_aHZM.js","DynamicMarkdown-DO1Fz7ar.js","SectionHeading-mwKBArs3.js","axios-vUo_bRtp.js","Markdown-C3KUTGJN.js","clsx-C6CAjViH.js","lib--scc4DXi.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-C3vb5JQZ.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-C8Hisf3g.js"]}