Webhooks
当您的 AgentSend 账户中发生事件时获取实时通知 — 收到新邮件、投递确认、检测到退信等。
概述
Instead of polling the API to check for new messages, webhooks let AgentSend push event data to your server the moment something happens. Register an HTTPS endpoint and AgentSend will send a POST request with a JSON payload whenever a subscribed event fires.
Webhooks are the recommended way to build reactive agents. When a reply lands in your agent's inbox, your application receives the full message payload within seconds and can act on it immediately.
Webhook endpoints must be publicly accessible over HTTPS. Localhost URLs are not accepted. Use a tool like ngrok or a tunnel service when developing locally.
创建 Webhook
Register a new webhook by sending a POST request to /webhooks. You must provide a url field; all other fields are optional.
/webhooks
| 参数 | 类型 | 说明 |
|---|---|---|
url 必填 |
string | The HTTPS URL AgentSend will POST events to. |
description |
string | A human-readable label to identify the webhook in the dashboard. |
events |
string[] | List of event types to subscribe to. Omit to receive all events. |
const res = await fetch("https://api.agentsend.io/webhooks", { method: "POST", headers: { "x-api-key": process.env.AGENTSEND_API_KEY, "Content-Type": "application/json", }, body: JSON.stringify({ url: "https://myapp.example.com/hooks/agentsend", description: "Production inbox events", events: ["message.received", "message.bounced"], }), }); const webhook = await res.json(); console.log(webhook.id); // wh_01j9... console.log(webhook.secret); // whsec_... store this securely!
The secret is returned only once in the creation response. Store it in a secure environment variable immediately — it cannot be retrieved again, but you can rotate it via PUT /webhooks/{id}.
事件类型
Subscribe to specific events by passing their identifiers in the events array. If you omit the array, AgentSend delivers all event types to your endpoint.
| 事件 | 说明 |
|---|---|
domain.verified |
A custom domain has passed DNS verification and is ready to use. |
message.received |
An inbound email has arrived in one of your agent's inboxes. |
message.sent |
An outbound message has been accepted and queued for delivery. |
message.delivered |
The recipient's mail server confirmed successful delivery. |
message.bounced |
The message could not be delivered (hard or soft bounce). |
message.complained |
The recipient marked the message as spam via their mail client. |
Webhook 载荷
Every webhook delivery is a POST request with a Content-Type: application/json body. The payload has a consistent envelope regardless of event type.
{
"id": "evt_01j9xkq7z8abc",
"type": "message.received",
"createdAt": "2026-04-16T10:23:45.000Z",
"webhookId": "wh_01j9abc123",
"data": {
"id": "msg_01j9xkp4n5def",
"inboxId": "inbox_01j8mq3r2t",
"threadId": "thr_01j9xkp4m1ghi",
"fromAddress": "alice@example.com",
"fromName": "Alice Chen",
"toAddresses": ["a1b2c3@agentsend.io"],
"subject": "Re: Your proposal",
"bodyText": "Looks great, let's move forward.",
"bodyHtml": "<p>Looks great, let's move forward.</p>",
"hasAttachments": false,
"receivedAt": "2026-04-16T10:23:44.812Z"
}
}验证签名
Every webhook request includes an X-AgentSend-Signature header. This is an HMAC-SHA256 hash of the raw request body, signed with your webhook's secret. Always verify this signature before processing a delivery to protect against forged requests.
import crypto from "node:crypto"; app.post("/hooks/agentsend", express.raw({ type: "application/json" }), (req, res) => { const sig = req.headers["x-agentsend-signature"]; const secret = process.env.AGENTSEND_WEBHOOK_SECRET; const expected = crypto .createHmac("sha256", secret) .update(req.body) // raw Buffer — do NOT parse JSON first .digest("hex"); if (!crypto.timingSafeEqual( Buffer.from(sig), Buffer.from(expected) )) { return res.status(401).send("Invalid signature"); } const event = JSON.parse(req.body); // handle event.type … res.sendStatus(200); });
import hmac, hashlib, os from flask import Flask, request, abort app = Flask(__name__) @app.route("/hooks/agentsend", methods=["POST"]) def webhook(): sig = request.headers.get("X-AgentSend-Signature", "") secret = os.environ["AGENTSEND_WEBHOOK_SECRET"].encode() expected = hmac.new(secret, request.data, hashlib.sha256).hexdigest() if not hmac.compare_digest(sig, expected): abort(401) event = request.get_json() # handle event["type"] … return "", 200
Always use a constant-time comparison (e.g. crypto.timingSafeEqual or hmac.compare_digest) when checking signatures to prevent timing attacks.
重试策略
AgentSend considers a delivery successful when your endpoint responds with any 2xx HTTP status code within 10 seconds. If the request times out or returns a non-2xx response, the delivery is retried with exponential back-off:
| 尝试 | 距上次尝试的延迟 |
|---|---|
| 第 1 次重试 | 5 秒 |
| 第 2 次重试 | 30 秒 |
| 第 3 次重试 | 5 分钟 |
| 第 4 次重试 | 30 分钟 |
| 第 5 次重试 | 2 小时 |
After 5 failed retries (6 total attempts) the delivery is marked as failed and no further attempts are made. You can inspect failed deliveries in the delivery logs and manually replay them from the dashboard.
Respond with 200 OK as quickly as possible. If your processing logic takes time, accept the payload immediately and handle it asynchronously with a queue or background job.
管理 Webhooks
The webhooks API lets you list, update, and delete your registered endpoints.
列出 webhooks
返回您账户中注册的所有 webhooks。
# GET /webhooks curl https://api.agentsend.io/webhooks \ -H "x-api-key: $AGENTSEND_API_KEY"
更新 webhook
Change the URL, description, or subscribed event types. You can also rotate the signing secret by passing "rotateSecret": true — the response will include a new secret.
# PUT /webhooks/{id} curl -X PUT https://api.agentsend.io/webhooks/wh_01j9abc123 \ -H "x-api-key: $AGENTSEND_API_KEY" \ -H "Content-Type: application/json" \ -d '{"events": ["message.received", "message.delivered", "message.bounced"]}'
删除 webhook
永久删除 webhook。在删除生效之前,正在进行中的投递仍会尝试。
# DELETE /webhooks/{id} curl -X DELETE https://api.agentsend.io/webhooks/wh_01j9abc123 \ -H "x-api-key: $AGENTSEND_API_KEY"
活动监控
获取特定 webhook 的近期事件量和错误率摘要。
# GET /webhooks/activity curl "https://api.agentsend.io/webhooks/activity?webhookId=wh_01j9abc123" \ -H "x-api-key: $AGENTSEND_API_KEY"
投递日志
Every delivery attempt is recorded. Query the logs endpoint to inspect the full history for a webhook, including HTTP response codes, response bodies, and timing.
GET/webhooks/logs
| 查询参数 | 类型 | 说明 |
|---|---|---|
webhookId |
string | 过滤特定 webhook 的日志。 |
status |
string | success, failed, or pending. |
limit |
number | 返回的记录数(默认 50,最大 200)。 |
before |
string | 分页游标;传入最后一条记录的 id。 |
# Fetch failed deliveries for a webhook curl "https://api.agentsend.io/webhooks/logs?webhookId=wh_01j9abc123&status=failed" \ -H "x-api-key: $AGENTSEND_API_KEY"
Each log entry includes:
- id — Unique delivery attempt ID.
- eventId — The originating event ID.
- eventType — e.g.
message.received. - status —
success,failed, orpending. - httpStatus — The HTTP response code returned by your endpoint.
- durationMs — Round-trip time in milliseconds.
- attempt — Which attempt this was (1 = first delivery).
- createdAt — Timestamp of the attempt.