Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DataTalksClub/datamailer/llms.txt

Use this file to discover all available pages before exploring further.

POST /api/subscriptions/unsubscribe records an unsubscribe for an existing or new contact. The required scope field controls how broadly the unsubscribe applies — from a single client integration, across every client in an audience, or globally across all marketing email managed by Datamailer. The contact is upserted by normalized email if it does not exist yet, so this endpoint is safe to call even for addresses that have never subscribed.

Authentication

All requests must include a Bearer token issued for the target client.
Authorization: Bearer <client-api-key>

Request

Method and path: POST /api/subscriptions/unsubscribe Content-Type: application/json

Body Parameters

email
string
required
The contact’s email address. Trimmed and validated; looked up by its normalized (lowercased) form.
audience
string
required
Slug of the audience the contact belongs to. Must exist within the authenticated client’s organization.
client
string
required
Slug of the authenticated client. Must match the token’s client slug. Cross-client writes return HTTP 403.
scope
string
required
How broadly to apply the unsubscribe. One of:
  • client — marks the client-scoped subscription as unsubscribed.
  • audience — marks every client subscription within the audience as unsubscribed.
  • global — sets global_unsubscribed_at on the contact, blocking all marketing email managed by Datamailer.
reason
string
Optional free-text reason for the unsubscribe. Stored in unsubscribe_reason on the affected subscription(s). Defaults to an empty string.

Scope Behavior

client

Calls unsubscribe_contact with the specific client argument. Only the subscription record for this audience + client pair is updated.

audience

Calls unsubscribe_contact without a client argument. All client subscriptions within the audience are set to unsubscribed, and an audience-level subscription record is created if one does not exist.

global

Sets global_unsubscribed_at on the contact record. This flag is checked before every marketing send and blocks delivery across all audiences and all clients managed by this Datamailer instance.

Response

HTTP 200 OK on success. The response is the standard contact status payload plus a scope echo field.
contact_id
integer
Internal ID of the contact record.
email
string
Normalized email address.
exists
boolean
true when the contact has a subscription visible to the authenticated client.
verified
boolean
Whether the contact or subscription is verified.
verified_at
string | null
ISO 8601 timestamp, or null.
email_validation
object
Current email validation state for the contact.
global_unsubscribed
boolean
true when global_unsubscribed_at is set on the contact — this will be true after a global scope unsubscribe.
hard_bounced
boolean
true when the contact has a hard bounce on record.
complained
boolean
true when the contact has filed a spam complaint.
audience
object
client
object
can_send_marketing
boolean
Whether marketing email can currently be sent to this contact from this client.
can_send_transactional
boolean
Whether transactional email can currently be sent to this contact.
scope
string
Echo of the scope value that was applied: client, audience, or global.

Examples

Unsubscribe from a single client

curl -X POST https://datamailer.example.com/api/subscriptions/unsubscribe \
  -H "Authorization: Bearer dm_dtccourses_demo_transactional_email_key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "learner@example.com",
    "audience": "dtc-courses",
    "client": "dtc-courses",
    "scope": "client",
    "reason": "user-requested"
  }'

Unsubscribe from the whole audience

curl -X POST https://datamailer.example.com/api/subscriptions/unsubscribe \
  -H "Authorization: Bearer dm_dtccourses_demo_transactional_email_key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "learner@example.com",
    "audience": "dtc-courses",
    "client": "dtc-courses",
    "scope": "audience",
    "reason": "unsubscribed-all-courses"
  }'

Global unsubscribe

curl -X POST https://datamailer.example.com/api/subscriptions/unsubscribe \
  -H "Authorization: Bearer dm_dtccourses_demo_transactional_email_key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "learner@example.com",
    "audience": "dtc-courses",
    "client": "dtc-courses",
    "scope": "global",
    "reason": "list-unsubscribe-header"
  }'

Response (global scope example)

{
  "contact_id": 42,
  "email": "learner@example.com",
  "exists": true,
  "verified": true,
  "verified_at": "2024-09-01T10:00:00Z",
  "email_validation": {
    "status": "unknown",
    "reason": "",
    "validated_at": null
  },
  "global_unsubscribed": true,
  "hard_bounced": false,
  "complained": false,
  "audience": {
    "slug": "dtc-courses",
    "subscribed": false,
    "status": null,
    "verified": false,
    "verified_at": null,
    "unsubscribed_at": null,
    "unsubscribe_reason": ""
  },
  "client": {
    "slug": "dtc-courses",
    "subscribed": true,
    "status": "subscribed",
    "verified": true,
    "verified_at": "2024-09-01T10:00:00Z",
    "unsubscribed_at": null,
    "unsubscribe_reason": ""
  },
  "can_send_marketing": false,
  "can_send_transactional": true,
  "scope": "global"
}
The global scope sets global_unsubscribed_at on the contact record, which blocks all marketing email across every audience and every client managed by this Datamailer instance. This cannot be reversed via the unsubscribe endpoint. To clear a global unsubscribe, use PATCH /api/contacts/{contact_id}/suppression with "global_unsubscribed": false.

Build docs developers (and LLMs) love