PlopPlop Docs

Webhooks

Receive push notifications when emails arrive instead of polling the API.

Webhooks let your server receive real-time POST requests when events happen in your mailbox. Instead of polling the Messages API, you register an HTTPS endpoint and plop delivers events as they occur.

Webhooks are available on Team plans and above.

Supported events

EventDescription
email.receivedA new email was delivered to one of your mailboxes

Setup

  1. Go to Settings → Webhooks in the dashboard.
  2. Click Create endpoint and enter an HTTPS URL.
  3. Copy the signing secret (whsec_…). It is shown once — store it securely.

The endpoint must return a 2xx status within 10 seconds or the delivery is marked as failed.

Payload

Every webhook POST includes a JSON body:

{
  "event": "email.received",
  "timestamp": "2026-02-06T12:00:00.000Z",
  "data": {
    "id": "msg_abc123",
    "mailbox": "qa",
    "mailboxWithTag": "qa+signup",
    "tag": "signup",
    "from": "sender@example.com",
    "to": "qa+signup@in.plop.email",
    "subject": "Welcome to Acme",
    "receivedAt": "2026-02-06T11:59:58.000Z",
    "domain": "in.plop.email"
  }
}

Signature verification

Every request includes an X-Plop-Signature header:

X-Plop-Signature: t=1738843200,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8f9

The signature is an HMAC-SHA256 of ${timestamp}.${body} using your signing secret. Always verify the signature before processing the payload.

Node.js example

import { createHmac, timingSafeEqual } from "node:crypto";

function verifyWebhook(
  body: string,
  header: string,
  secret: string,
): boolean {
  const [tPart, v1Part] = header.split(",");
  const timestamp = tPart.replace("t=", "");
  const receivedSig = v1Part.replace("v1=", "");

  // Reject signatures older than 5 minutes
  const age = Math.floor(Date.now() / 1000) - Number(timestamp);
  if (age > 300) return false;

  const expected = createHmac("sha256", secret)
    .update(`${timestamp}.${body}`)
    .digest("hex");

  return timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(receivedSig),
  );
}

Delivery behavior

  • Retries: Failed deliveries are retried up to 3 times with exponential backoff.
  • Timeout: Your endpoint must respond within 10 seconds.
  • Logs: View delivery attempts, status codes, and latency in Settings → Webhooks → Deliveries.

Manage via API

You can also manage webhooks programmatically using the REST API or SDKs.

REST API

MethodEndpointDescription
GET/v1/webhooksList all webhook endpoints
POST/v1/webhooksCreate a new endpoint
DELETE/v1/webhooks/{id}Delete an endpoint
PATCH/v1/webhooks/{id}Toggle active/inactive
GET/v1/webhooks/{id}/deliveriesList delivery attempts

All endpoints require an API key with api.full scope.

SDK example

import { Plop } from "@plop-email/sdk";

const plop = new Plop();
const { data } = await plop.webhooks.create({
  url: "https://example.com/webhook",
});
console.log(data.secret); // store this securely

Plan requirement

Webhooks require the Team plan or higher. Starter plan users can upgrade from the billing page.

On this page