Unsubscribe
Manage one-click unsubscribe, resubscription, and automatic suppression from bounces and complaints.
Kraiter provides built-in unsubscribe and suppression management to keep your sending compliant and your sender reputation healthy. Understanding the difference between unsubscribe and suppression is important for managing your contact list effectively.
One-click unsubscribe
Kraiter implements one-click unsubscribe following RFC 8058. Every email sent through the platform includes two headers:
List-Unsubscribe: <https://api.kraiter.com/unsubscribe/abc123>
List-Unsubscribe-Post: List-Unsubscribe=One-ClickThese headers allow email clients (Gmail, Apple Mail, Yahoo, and others) to display a prominent unsubscribe button directly in their UI. When a recipient clicks it, a POST request is sent to Kraiter's unsubscribe endpoint, and the contact is immediately marked as unsubscribed.
How it works
- Kraiter adds the
List-UnsubscribeandList-Unsubscribe-Postheaders to every outgoing email - The recipient's email client displays an unsubscribe option (e.g. the "Unsubscribe" link at the top of Gmail messages)
- When the recipient clicks it, the email client sends a POST request to Kraiter
- Kraiter marks the contact as unsubscribed (
unsubscribed: true) - An
email.unsubscribedsystem event is recorded - Future sequence and campaign emails to this contact are blocked
This is handled entirely by Kraiter — you do not need to build any unsubscribe infrastructure.
In-email unsubscribe link
In addition to the header-based mechanism, you should include a visible unsubscribe link in your email footer. Kraiter provides an unsubscribe URL you can use in your templates:
<mj-section>
<mj-column>
<mj-text align="center" font-size="12px" color="#999999">
<a href="{{ unsubscribeUrl }}">Unsubscribe</a> from these emails.
</mj-text>
</mj-column>
</mj-section>The {{ unsubscribeUrl }} variable is automatically available in all templates and is unique to each send.
Unsubscribed contacts
When a contact unsubscribes:
- They are removed from all active sequence enrolments
- They will not receive future sequence or campaign emails
- They can still receive transactional emails if the send uses
ignoreUnsubscribe: true - Their contact record and event history are preserved
- They can be resubscribed via the API
Check whether a contact is unsubscribed:
const contact = await kraiter.contacts.get('alice@example.com');
if (contact.unsubscribed) {
console.log(`Unsubscribed at: ${contact.unsubscribedAt}`);
}Resubscription
If a contact wants to re-opt in, you can resubscribe them via the API:
await kraiter.contacts.resubscribe('alice@example.com');curl -X POST https://api.kraiter.com/contacts/alice%40example.com/resubscribe \
-H "Authorization: Bearer YOUR_API_KEY"Important: Only resubscribe contacts who have explicitly asked to receive emails again. Resubscribing contacts without their consent violates anti-spam regulations and damages your sender reputation.
Resubscription:
- Sets
unsubscribedtofalse - Does not re-enrol the contact in any sequences they were removed from
- Does not undo suppression — if the contact is also suppressed, the suppression must be addressed separately
Suppression
Suppression is a separate mechanism from unsubscribe. A contact is suppressed when Kraiter detects a delivery problem that makes it unsafe to continue sending to that address.
Suppression reasons
| Reason | Description |
|---|---|
bounce | A hard bounce was received — the email address does not exist or the mailbox is permanently unavailable |
complaint | The recipient reported the email as spam via their email provider's feedback loop |
How suppression works
- Kraiter receives a bounce or complaint notification via SES webhooks
- The contact is automatically marked as suppressed
- All future sends to this contact are blocked — including transactional emails
- The suppression reason and timestamp are recorded on the contact
Unlike unsubscribe, suppression blocks all sends including transactional. Sending to an address that has bounced or complained would damage your sender reputation with ISPs.
Checking suppression status
const contact = await kraiter.contacts.get('alice@example.com');
if (contact.suppressed) {
console.log(`Reason: ${contact.suppressionReason}`); // 'bounce' or 'complaint'
console.log(`Since: ${contact.suppressedAt}`);
}Unsubscribe vs suppression
These two states serve different purposes and have different implications:
| Unsubscribe | Suppression | |
|---|---|---|
| Initiated by | The recipient (opt-out) | The system (delivery failure) |
| Blocks marketing emails | Yes | Yes |
| Blocks transactional emails | No (with ignoreUnsubscribe) | Yes (all sends blocked) |
| Can be reversed | Yes, via resubscribe API | Must remove suppression first |
| Reason | Recipient preference | Technical delivery issue |
Managing suppressed contacts
List suppressed contacts:
const { items } = await kraiter.contacts.list({
suppressed: true,
});In most cases, you should not attempt to unsuppress contacts:
- Bounced contacts usually have invalid email addresses. Removing suppression and resending will result in another bounce and further harm your reputation.
- Complained contacts have explicitly reported you as spam. Sending to them again risks further complaints and potential blocklisting.
If you are certain a suppression was in error (e.g. a temporary mail server issue was misclassified as a hard bounce), contact support to review the suppression.
Best practices
- Never hide the unsubscribe link. Make it easy to find in your email footer. Hidden unsubscribe links lead to spam complaints, which are worse than unsubscribes.
- Respect unsubscribe immediately. Kraiter handles this automatically, but ensure your application also respects the contact's preference.
- Monitor suppression rates. A rising suppression rate indicates list quality issues. Clean your contact list regularly.
- Do not resubscribe without consent. Only resubscribe contacts who have explicitly asked to receive emails again.
- Use double opt-in for new contacts. Send a confirmation email before adding contacts to your active list. This reduces bounces and complaints.