PadiMail Docs
API reference

Webhooks

Endpoints that receive events, their secrets and their deliveries.

All requests go to https://api.padimail.app with Authorization: Bearer <your key>. Try these in the interactive reference with a pm_test_ key.

Add a webhook endpoint

POST/v1/webhooks

Body

FieldTypeRequiredNotes
urlstring (uri)YesAn HTTPS URL that answers 2xx within 10 seconds.
descriptionstringNo
event_types("email.queued" | "email.scheduled" | "email.deferred" | "email.sent" | "email.delivered" | "email.delivery_delayed" | "email.bounced" | "email.complained" | "email.opened" | "email.clicked" | "email.suppressed" | "email.held" | "email.released" | "email.rejected" | "email.failed" | "email.canceled" | "domain.verified" | "domain.failed" | "account.paused" | "account.resumed" | "account.quota_reached" | "account.usage_threshold" | "account.usage_spike")[]YesThe events to send, such as email.delivered.
format"padimail" | "resend"Noresend sends Resend's event names and svix-* headers.
mode"live" | "test"No

Send an Idempotency-Key header to make retries safe. The Node SDK adds one for you.

Example

import { PadiMail } from "@padimail/node";

const pm = new PadiMail(process.env.PADIMAIL_API_KEY);

const result = await pm.webhooks.create({
  url: "https://acme.ng/webhooks/padimail",
  event_types: ["email.delivered", "email.bounced", "email.complained"],
});

Response 200

{
  "id": "wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S",
  "object": "webhook",
  "mode": "live",
  "url": "https://acme.ng/webhooks/padimail",
  "description": "string",
  "event_types": ["email.queued"],
  "format": "padimail",
  "status": "enabled",
  "failing_since": "2026-10-27T13:05:09Z",
  "created_at": "2026-10-27T13:05:09Z",
  "secret": "whsec_…"
}

List webhook endpoints

GET/v1/webhooks

Query parameters

FieldTypeRequiredNotes
limitintegerNoPage size, 1 to 100. Default 50.
afterstringNoReturn items after this ID (the next value of the previous page).
beforestringNoReturn items before this ID.

Example

import { PadiMail } from "@padimail/node";

const pm = new PadiMail(process.env.PADIMAIL_API_KEY);

const result = await pm.webhooks.list();

Response 200

{
  "data": [
    {
      "id": "wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S",
      "object": "webhook",
      "mode": "live",
      "url": "https://acme.ng/webhooks/padimail",
      "description": "string",
      "event_types": ["email.queued"],
      "format": "padimail",
      "status": "enabled",
      "failing_since": "2026-10-27T13:05:09Z",
      "created_at": "2026-10-27T13:05:09Z"
    }
  ],
  "has_more": false,
  "next": "string"
}

Get a webhook endpoint

GET/v1/webhooks/{id}

Path parameters

FieldTypeRequiredNotes
idstringYes

Example

import { PadiMail } from "@padimail/node";

const pm = new PadiMail(process.env.PADIMAIL_API_KEY);

const result = await pm.webhooks.get("wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S");

Response 200

{
  "id": "wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S",
  "object": "webhook",
  "mode": "live",
  "url": "https://acme.ng/webhooks/padimail",
  "description": "string",
  "event_types": ["email.queued"],
  "format": "padimail",
  "status": "enabled",
  "failing_since": "2026-10-27T13:05:09Z",
  "created_at": "2026-10-27T13:05:09Z"
}

Update a webhook endpoint

PATCH/v1/webhooks/{id}

Path parameters

FieldTypeRequiredNotes
idstringYes

Body

FieldTypeRequiredNotes
urlstring (uri)No
descriptionstring | nullNo
event_types("email.queued" | "email.scheduled" | "email.deferred" | "email.sent" | "email.delivered" | "email.delivery_delayed" | "email.bounced" | "email.complained" | "email.opened" | "email.clicked" | "email.suppressed" | "email.held" | "email.released" | "email.rejected" | "email.failed" | "email.canceled" | "domain.verified" | "domain.failed" | "account.paused" | "account.resumed" | "account.quota_reached" | "account.usage_threshold" | "account.usage_spike")[]No
format"padimail" | "resend"No
status"enabled" | "disabled"No

Example

import { PadiMail } from "@padimail/node";

const pm = new PadiMail(process.env.PADIMAIL_API_KEY);

const result = await pm.webhooks.update("wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S", { status: "disabled" });

Response 200

{
  "id": "wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S",
  "object": "webhook",
  "mode": "live",
  "url": "https://acme.ng/webhooks/padimail",
  "description": "string",
  "event_types": ["email.queued"],
  "format": "padimail",
  "status": "enabled",
  "failing_since": "2026-10-27T13:05:09Z",
  "created_at": "2026-10-27T13:05:09Z"
}

Delete a webhook endpoint

DELETE/v1/webhooks/{id}

Path parameters

FieldTypeRequiredNotes
idstringYes

Example

import { PadiMail } from "@padimail/node";

const pm = new PadiMail(process.env.PADIMAIL_API_KEY);

const result = await pm.webhooks.remove("wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S");

Response 200

{ "id": "string", "object": "string", "deleted": true }

Rotate the signing secret (the old one works for 24 h)

POST/v1/webhooks/{id}/rotate-secret

Path parameters

FieldTypeRequiredNotes
idstringYes

Example

import { PadiMail } from "@padimail/node";

const pm = new PadiMail(process.env.PADIMAIL_API_KEY);

const result = await pm.webhooks.rotateSecret("wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S");

Response 200

{
  "id": "wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S",
  "object": "webhook",
  "mode": "live",
  "url": "https://acme.ng/webhooks/padimail",
  "description": "string",
  "event_types": ["email.queued"],
  "format": "padimail",
  "status": "enabled",
  "failing_since": "2026-10-27T13:05:09Z",
  "created_at": "2026-10-27T13:05:09Z",
  "secret": "whsec_…"
}

Send a test event

POST/v1/webhooks/{id}/test

Path parameters

FieldTypeRequiredNotes
idstringYes

Body

FieldTypeRequiredNotes
event_type"email.queued" | "email.scheduled" | "email.deferred" | "email.sent" | "email.delivered" | "email.delivery_delayed" | "email.bounced" | "email.complained" | "email.opened" | "email.clicked" | "email.suppressed" | "email.held" | "email.released" | "email.rejected" | "email.failed" | "email.canceled" | "domain.verified" | "domain.failed" | "account.paused" | "account.resumed" | "account.quota_reached" | "account.usage_threshold" | "account.usage_spike"Yes

Example

import { PadiMail } from "@padimail/node";

const pm = new PadiMail(process.env.PADIMAIL_API_KEY);

const result = await pm.webhooks.test("wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S", { event_type: "email.delivered" });

Response 200

{ "delivery_id": "whd_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S" }

List deliveries (kept 30 days)

GET/v1/webhooks/{id}/deliveries

Path parameters

FieldTypeRequiredNotes
idstringYes

Query parameters

FieldTypeRequiredNotes
limitintegerNoPage size, 1 to 100. Default 50.
afterstringNoReturn items after this ID (the next value of the previous page).
beforestringNoReturn items before this ID.
status"pending" | "succeeded" | "failed"No

Example

import { PadiMail } from "@padimail/node";

const pm = new PadiMail(process.env.PADIMAIL_API_KEY);

const result = await pm.webhooks.deliveries.list("wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S", { status: "failed" });

Response 200

{
  "data": [
    {
      "id": "whd_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S",
      "webhook_id": "wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S",
      "event_id": "evt_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S",
      "event_type": "string",
      "attempt": 0,
      "status": "pending",
      "response_status": 0,
      "response_body_excerpt": "string",
      "duration_ms": 0,
      "next_attempt_at": "2026-10-27T13:05:09Z",
      "created_at": "2026-10-27T13:05:09Z"
    }
  ],
  "has_more": false,
  "next": "string"
}

Retry a delivery now

POST/v1/webhooks/{id}/deliveries/{did}/retry

Path parameters

FieldTypeRequiredNotes
idstringYes
didstringYes

Example

import { PadiMail } from "@padimail/node";

const pm = new PadiMail(process.env.PADIMAIL_API_KEY);

const result = await pm.webhooks.deliveries.retry("wh_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S", "whd_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S");

Response 200

{ "delivery_id": "whd_01JBX7Q3F6ZK0Q9W1Y2R3T4V5S" }
Was this page helpful?

On this page