tinysend

Webhooks let you receive HTTP POST requests when events happen in tinysend. Use them to sync data, trigger automations, or power AI agents.

Setup

  1. POST /webhooks with a URL and list of events
  2. tinysend sends a test event to verify your endpoint
  3. save the secret from the response — it’s shown only once
curl -X POST https://api.tinysend.com/v1/webhooks \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/webhook", "events": ["post.sent", "subscriber.created"]}'

Events

Events use entity.action naming. 30 events across 6 entities.

post

A post is a content piece broadcast to a newsletter’s subscribers.

eventwhen
post.createddraft created (UI, email, or API)
post.updatedcontent or settings changed
post.sentuser/agent triggered sending
post.deliveredall emails for this post resolved
post.pausedbroadcast paused mid-send
post.resumedbroadcast resumed after pause
post.cancelledbroadcast cancelled
post.viewedsomeone viewed the post on the archive website
post.likedsomeone reacted to the post

post.sent fires at the moment of approval, not when batches finish submitting. post.delivered fires when every recipient has a terminal status (delivered + bounced + failed = total).

email

An email is any message in the system — inbound or outbound, broadcast or direct.

eventwhen
email.receivedinbound email arrived in a mailbox
email.sentoutbound email submitted to provider
email.deliveredprovider confirmed inbox delivery
email.bouncedhard or soft bounce
email.openedtracking pixel fired
email.clickedtracked link clicked
email.complainedrecipient filed spam complaint
email.repliedrecipient replied to an email

subscriber

A person in a specific newsletter.

eventwhen
subscriber.createdadded to a newsletter (form, API, import, or agent)
subscriber.confirmeddouble opt-in confirmed
subscriber.unsubscribedunsubscribed via link, API, or manually
subscriber.deletedremoved from a newsletter

contact

A person across all newsletters in your account.

eventwhen
contact.creatednew contact
contact.updatedcontact data changed
contact.deletedcontact removed

list

The audience container — a newsletter, waitlist, or announcement (the event names keep the list.* prefix).

eventwhen
list.creatednew newsletter created
list.updatedsettings changed
list.deletednewsletter removed

mailbox

An addressable email endpoint.

eventwhen
mailbox.creatednew mailbox created
mailbox.updatedsettings changed
mailbox.deletedmailbox removed

Payload

Every webhook delivery uses this envelope:

{
  "id": "01jx...",
  "type": "post.sent",
  "created_at": "2025-06-09T12:00:00Z",
  "data": {
    "post_id": "01jx...",
    "list_id": "01jx...",
    "subject": "Weekly update"
  }
}

Verifying signatures

Each delivery includes an HMAC-SHA256 signature in the X-Tinysend-Signature header, computed with the secret returned at subscription creation.

const crypto = require('crypto');

function verify(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Headers

headerdescription
X-Tinysend-Eventevent type (e.g. post.sent)
X-Tinysend-SignatureHMAC-SHA256 hex signature
X-Tinysend-Delivery-Idunique delivery ID for idempotency

Delivery

  • timeout: 10 seconds
  • retries: 3 attempts with backoff
  • auto-disable: after 10 consecutive failures
  • your endpoint must return 2xx to acknowledge

Managing webhooks

methodendpointdescription
POST/webhookscreate subscription
GET/webhookslist subscriptions
GET/webhooks/:idget subscription details
PATCH/webhooks/:idupdate URL, events, or status
DELETE/webhooks/:iddelete subscription
POST/webhooks/:id/testsend test event
GET/webhooks/:id/deliverieslist recent deliveries