Skip to main content

Email Forwards API

Forward every email an inbox receives to a webhook URL, as signed JSON. For the payload, the signature and how to test a handler locally, see Forward email to webhooks.

Forwards need a paid plan. The plan's forwarding destinations limit caps forwards per inbox: Pro 3, Production and Scale unlimited. All routes use the usual authentication.

RouteResult
GET /api/v1/inboxes/:id/forwardsList an inbox's forwards
POST /api/v1/inboxes/:id/forwardsCreate a forward
GET /api/v1/inboxes/:id/forwards/:forward_idGet a forward
PATCH /api/v1/inboxes/:id/forwards/:forward_idUpdate a forward
DELETE /api/v1/inboxes/:id/forwards/:forward_idDelete a forward and its delivery log
GET /api/v1/inboxes/:id/forwards/:forward_id/deliveriesList a forward's latest deliveries
POST /api/v1/inboxes/:id/forwards/:forward_id/testSend a test delivery
POST /api/v1/inboxes/:id/emails/:email_id/redeliverDeliver a stored email again

The forward object​

{
"id": "8f0c2a6e-1d4b-4e7a-9c3f-2b1a0d9e8c7f",
"inbox_id": "5c1d0e9a-3f7b-4f0e-9c1a-1b2e3f4a5b6c",
"url": "https://example.com/inbound-email",
"enabled": true,
"filters": { "to": null, "from": null, "subject_contains": "Re:" },
"signing_secret": "whsec_MfKQ9r8GKYqrTwJnYk3jYQ2JmLz7rK1V",
"created_at": "2026-10-12T10:00:00Z",
"updated_at": "2026-10-12T10:00:00Z"
}

signing_secret signs every delivery (see Verify the signature). It's left out for read-only API keys.

List forwards​

GET /api/v1/inboxes/:id/forwards

Returns {"data": [forward, …]}, oldest first.

Create a forward​

POST /api/v1/inboxes/:id/forwards
curl -X POST https://app.hooklistener.com/api/v1/inboxes/INBOX_ID/forwards \
-H "Authorization: Bearer hklst_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/inbound-email",
"filters": {"to": "[email protected]"}
}'
FieldTypeRequiredDescription
urlstringYesPublic http(s) URL that receives each email. Private and local addresses are refused
enabledbooleanNoWhether the forward delivers email. Default true
filters.tostringNoOnly emails sent to this exact address, case-insensitive
filters.fromstringNoOnly emails whose From contains this text, case-insensitive
filters.subject_containsstringNoOnly emails whose subject contains this text, case-insensitive

When several filters are set, all must match. Filters can also be sent as top-level to, from and subject_contains fields, and the body can be wrapped as {"forward": {…}}.

Returns 201 with {"data": forward}, including its signing_secret, and a Location header.

Errors:

StatusWhen
403Your plan doesn't include forwarding, or the inbox already has the plan's number of forwards. The body includes error and an upgrade object
422Invalid attributes, e.g. a URL that isn't public

Get a forward​

GET /api/v1/inboxes/:id/forwards/:forward_id

Returns {"data": forward}.

Update a forward​

PATCH /api/v1/inboxes/:id/forwards/:forward_id
# Pause a forward
curl -X PATCH https://app.hooklistener.com/api/v1/inboxes/INBOX_ID/forwards/FORWARD_ID \
-H "Authorization: Bearer hklst_your_api_key" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'

Takes the same fields as Create a forward. Updates are partial: fields you leave out keep their value, and null or "" clears a filter. The signing secret doesn't change.

Returns {"data": forward}.

Delete a forward​

DELETE /api/v1/inboxes/:id/forwards/:forward_id

Deletes the forward and its delivery log. Returns 204 No Content.

List deliveries​

GET /api/v1/inboxes/:id/forwards/:forward_id/deliveries

Latest first. limit sets how many (default 20, max 100).

{
"data": [
{
"id": "3e9b7c1d-5a2f-4d8e-b6c0-9f1a2e3d4c5b",
"forward_id": "8f0c2a6e-1d4b-4e7a-9c3f-2b1a0d9e8c7f",
"email_id": "b72d4c1e-6a0f-4a51-9f3e-2d8c1b7e9a10",
"webhook_id": "msg_b72d4c1e-6a0f-4a51-9f3e-2d8c1b7e9a10",
"trigger": "email",
"status": "succeeded",
"attempts": 2,
"status_code": 200,
"duration_ms": 143,
"error": null,
"response_snippet": "{\"ok\":true}",
"attempt_log": [
{ "attempt": 1, "status_code": 502, "duration_ms": 87, "error": "HTTP 502", "at": "2026-10-12T10:02:12Z" },
{ "attempt": 2, "status_code": 200, "duration_ms": 143, "error": null, "at": "2026-10-12T10:02:27Z" }
],
"last_attempt_at": "2026-10-12T10:02:27Z",
"completed_at": "2026-10-12T10:02:27Z",
"created_at": "2026-10-12T10:02:11Z"
}
]
}
FieldDescription
triggeremail (the automatic delivery), redeliver or test
statuspending, retrying, succeeded, failed, or skipped (the forward was paused before a queued delivery ran)
email_idThe forwarded email, or null for a test with the sample email
webhook_idThe webhook-id header sent; the same for every delivery of one email, msg_test_… for tests
response_snippetFirst 1 KB of your endpoint's answer
attempt_logEvery attempt with its status code, duration and error

The automatic delivery is retried with exponential backoff for up to 8 attempts (about 30 minutes); redeliveries and tests make one attempt. Deliveries of an email are deleted with the email when it leaves your plan's retention window.

Send a test​

POST /api/v1/inboxes/:id/forwards/:forward_id/test

Sends the inbox's latest email to the forward, or a sample email when the inbox is empty, in one attempt. Works on a paused forward. Returns 202 Accepted with {"data": delivery}; poll the deliveries for the result.

Redeliver an email​

POST /api/v1/inboxes/:id/emails/:email_id/redeliver
curl -X POST https://app.hooklistener.com/api/v1/inboxes/INBOX_ID/emails/EMAIL_ID/redeliver \
-H "Authorization: Bearer hklst_your_api_key" \
-H "Content-Type: application/json" \
-d '{"forward_id": "FORWARD_ID"}'
FieldRequiredDescription
forward_idNoDeliver to this forward only, even if it's paused or its filters don't match. Without it, the email goes to every enabled forward whose filters match

Each redelivery makes one attempt and reuses the email's webhook-id, so receivers that deduplicate on it ignore emails they already processed. Returns 202 Accepted with {"data": [delivery, …]}.

Errors:

StatusWhen
400No forward_id, and no enabled forward of the inbox matches the email
403Your plan doesn't include forwarding
404Unknown inbox, email or forward