Newsletters
Public REST API for managing newsletters, subscribers, and issues. Full CRUD plus subscribe / DOI confirm / unsubscribe / send-issue endpoints. Pairs with the embed widget and hosted subscribe page.
Newsletters are the recurring-send counterpart to broadcasts. Each newsletter has its own subscriber list, branding, double-opt-in (DOI) flow, and history of issues.
The newsletter API is exposed at /v1/newsletters/... and is API-key authenticated, scoped to your workspace.
Public sign-up flows:
- Hosted subscribe page —
/n/:slug(Next.js dashboard app) renders a public subscribe page with your branding. Newsletter signups land here when shared via QR code or social link. - Embed widget —
/n/:slug/embedis an iframe-friendly subscribe form you can drop into any site with a single<iframe>tag. Branded to your newsletter's accent color and logo. - Direct API —
POST /v1/newsletters/:id/subscribersaccepts subscribe requests programmatically, perfect for headless integrations.
Double opt-in (DOI):
When DOI is enabled (the default), a new subscriber is created with status: 'pending' and a confirmation email is sent. The subscriber clicks the confirm link, which sets status: 'active'. Issues only fan out to active subscribers.
Auto-suppression cascade:
When a subscriber's email is added to suppression_list (hard bounce, repeated soft bounces, complaint, or manual), all matching newsletter_subscribers rows for that email in the same workspace are automatically flipped to status: 'unsubscribed' with the suppression reason recorded in metadata.unsubscribe_reason. Bounce / Complaint badges show on the subscriber row in the dashboard so you can tell dead addresses from voluntary opt-outs at a glance.
Issue throughput:
Sending an issue queues one email per active subscriber, drained at the shared 12 emails/sec worker limit (which sits under AWS SES's 14/sec account ceiling). A newsletter with 5,000 active subscribers takes ~7 minutes to fully ship. The dashboard shows live progress while the issue is sending.
/v1/newslettersList all newsletters in the current workspace.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
curl https://api.posthawk.dev/v1/newsletters \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:idGet a single newsletter by ID, including branding, DOI settings, and subscriber count.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
curl https://api.posthawk.dev/v1/newsletters/{id} \
-H "Authorization: Bearer your_api_key"/v1/newslettersCreate a new newsletter. Accepts name, slug, from_email, from_name, accent_color, logo_url, double_opt_in, and other branding fields.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Body
namestringrequiredDisplay name (e.g. "Weekly Digest")
slugstringrequiredURL slug — used in /n/:slug public pages
from_emailstringoptionalSender email — domain must be verified for sending
from_namestringoptionalDisplay name on outbound emails
descriptionstringoptionalShort description shown on the subscribe page
double_opt_inbooleanoptionalWhether to require double-opt-in confirmation. Default: true
accent_colorstringoptionalHex color for branded UI (subscribe page, confirm email, embed widget)
logo_urlstringoptionalURL of your newsletter logo
curl -X POST https://api.posthawk.dev/v1/newsletters \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key" \
-d '{
"name": "Jane Doe",
"slug": "weekly-digest",
"from_email": "news@yourdomain.com",
"from_name": "Acme Weekly",
"description": "Production webhook",
"double_opt_in": true,
"accent_color": "#8262ff",
"logo_url": "https://yourdomain.com/logo.png"
}'/v1/newsletters/:idUpdate a newsletter. Only provided fields are updated.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
curl -X PATCH https://api.posthawk.dev/v1/newsletters/{id} \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:idDelete a newsletter. Cascades to subscribers and issues.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
curl -X DELETE https://api.posthawk.dev/v1/newsletters/{id} \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:id/subscribersList subscribers for a newsletter. Supports status filter (active / pending / unsubscribed), search, and pagination.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
Query Parameters
statusstringoptionalactive, pending, or unsubscribed
searchstringoptionalMatch against email or name
pagenumberoptionalPage number (default: 1)
curl https://api.posthawk.dev/v1/newsletters/{id}/subscribers \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:id/subscribers/:subscriberIdGet a single subscriber.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
curl https://api.posthawk.dev/v1/newsletters/{id}/subscribers/{subscriberId} \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:id/subscribersAdd a subscriber. With DOI enabled, creates a pending subscriber and sends the confirmation email. With DOI disabled, creates an active subscriber immediately. Idempotent — duplicate emails return the existing subscriber.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
Body
emailstringrequiredSubscriber email (lowercased)
namestringoptionalSubscriber display name
sourcestringoptionalTag indicating where the signup came from (e.g. "embed", "footer", "import")
metadataobjectoptionalArbitrary JSON metadata to attach to the subscriber
curl -X POST https://api.posthawk.dev/v1/newsletters/{id}/subscribers \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key" \
-d '{
"email": "user@example.com",
"name": "Jane Doe",
"source": "embed",
"metadata": {
"source": "website"
}
}'/v1/newsletters/:id/subscribers/:subscriberId/unsubscribeUnsubscribe a subscriber. Flips status to unsubscribed and records the timestamp. The public one-click unsubscribe link in newsletter footers also lands here.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
curl -X POST https://api.posthawk.dev/v1/newsletters/{id}/subscribers/{subscriberId}/unsubscribe \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:id/subscribers/:subscriberId/resend-confirmationResend the DOI confirmation email to a pending subscriber. Useful when the original was lost in spam.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
curl -X POST https://api.posthawk.dev/v1/newsletters/{id}/subscribers/{subscriberId}/resend-confirmation \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:id/subscribers/:subscriberIdPermanently delete a subscriber. Use POST /unsubscribe to keep the record for analytics.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
curl -X DELETE https://api.posthawk.dev/v1/newsletters/{id}/subscribers/{subscriberId} \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:id/issuesList issues for a newsletter, ordered by created_at desc.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
curl https://api.posthawk.dev/v1/newsletters/{id}/issues \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:id/issues/:issueIdGet a single issue with HTML body, subject, and stats.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
curl https://api.posthawk.dev/v1/newsletters/{id}/issues/{issueId} \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:id/issuesCreate a draft issue.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
Body
subjectstringrequiredEmail subject line
html_bodystringrequiredHTML body (will be wrapped in newsletter branding)
preheaderstringoptionalShort preview text shown in inbox
scheduled_forstringoptionalISO 8601 datetime to send at; if omitted, the issue is created as a draft you must explicitly send
curl -X POST https://api.posthawk.dev/v1/newsletters/{id}/issues \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key" \
-d '{
"subject": "Hello from Posthawk",
"html_body": "<h1>This week at Acme</h1>",
"preheader": "Your weekly update",
"scheduled_for": "2026-06-15T09:00:00Z"
}'/v1/newsletters/:id/issues/:issueIdUpdate a draft or scheduled issue. Sent issues are immutable.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
curl -X PATCH https://api.posthawk.dev/v1/newsletters/{id}/issues/{issueId} \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:id/issues/:issueId/sendSend an issue immediately (or schedule it if scheduled_for is set on the issue). Fans out to active subscribers; pending and unsubscribed subscribers are skipped. Suppression list is checked at send time.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
curl -X POST https://api.posthawk.dev/v1/newsletters/{id}/issues/{issueId}/send \
-H "Authorization: Bearer your_api_key"/v1/newsletters/:id/issues/:issueId/scheduleSchedule a draft issue to send at a future time. The scheduled_for must be a valid ISO 8601 datetime at least 30 seconds out and no more than 30 days ahead. The issue must not already be sent and must have a body and a sender configured.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
issueIdstringrequiredIssue UUID
Body
scheduled_forstringrequiredISO 8601 datetime to send at (≥30s future, ≤30 days ahead)
curl -X POST https://api.posthawk.dev/v1/newsletters/news-uuid/issues/issue-uuid/schedule \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key" \
-d '{ "scheduled_for": "2026-06-20T14:00:00Z" }'/v1/newsletters/:id/issues/:issueId/cancelCancel a scheduled or in-flight issue send. Already-queued emails still deliver; no further subscribers are fanned out.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
issueIdstringrequiredIssue UUID
curl -X POST https://api.posthawk.dev/v1/newsletters/{id}/issues/{issueId}/cancel \
-H "Authorization: Bearer your_api_key"{
"success": true,
"status": "cancelled",
"alreadyQueued": 0
}/v1/newsletters/:id/issues/:issueId/statsGet per-issue delivery and engagement stats: totals for sent, delivered, opened, clicked, bounced, complained, and failed, plus first/last event timestamps.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
issueIdstringrequiredIssue UUID
curl https://api.posthawk.dev/v1/newsletters/{id}/issues/{issueId}/stats \
-H "Authorization: Bearer your_api_key"{
"total": 5000,
"pending": 0,
"sent": 5000,
"delivered": 4920,
"opened": 2150,
"clicked": 430,
"bounced": 60,
"complained": 5,
"failed": 20,
"first_event_at": "2026-06-15T09:00:00Z",
"last_event_at": "2026-06-15T09:08:00Z"
}/v1/newsletters/:id/issues/:issueId/send-testSend a test render of an issue to a single email address (typically your own) so you can preview the final email before broadcasting to all subscribers. Does not affect issue status or delivery counts.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API Key.
Path Parameters
idstringrequiredNewsletter UUID
issueIdstringrequiredIssue UUID
Body
tostringrequiredRecipient email address for the test send
curl -X POST https://api.posthawk.dev/v1/newsletters/news-uuid/issues/issue-uuid/send-test \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key" \
-d '{ "to": "you@yourdomain.com" }'