Webhooks
Tick Up đẩy sự kiện đến endpoint của bạn để bạn không phải poll. Hai webhook đã sẵn sàng cho production hôm nay bao phủ vòng đời email (Resend) và phản hồi của ứng viên (inbound email).
Cách webhook hoạt động
Bạn đăng ký một HTTPS endpoint mà chúng tôi POST JSON đến. Chúng tôi thử lại với exponential backoff nếu endpoint của bạn trả về non-2xx, và chúng tôi ký mỗi payload để bạn xác minh đúng là từ chúng tôi.
- Method: luôn là
POST - Content-Type:
application/json - Mã hóa: UTF-8
- Retry: tối đa 5 lần trong 30 phút cho phản hồi non-2xx
- Timeout: 10 giây — trả về nhanh, xử lý nền
Vòng đời email (Resend)
/api/v1/webhooks/resendCông khaiEndpoint nhận sự kiện Resend của chính Tick Up — để tham chiếu. Webhook phía khách hàng sẽ được phơi qua /webhooks/configure (sắp ra mắt).
Mọi email gửi qua Tick Up — gửi tay, bước drip, broadcast chiến dịch, xác nhận giao dịch — đều đi qua Resend. Resend đẩy cho chúng tôi một webhook cho mỗi sự kiện có ý nghĩa:
| Sự kiện | Khi nào kích hoạt |
|---|---|
email.delivered | Mail server của người nhận đã chấp nhận tin. |
email.opened | Người nhận đã load pixel theo dõi. |
email.clicked | Người nhận đã click vào link được theo dõi. |
email.bounced | Mail server từ chối tin (bounce cứng hoặc mềm). |
email.complained | Người nhận đã đánh dấu email là spam. |
email.failed | Gửi thất bại trước khi đến hàng đợi outbound của Resend. |
{
"type": "email.opened",
"created_at": "2026-05-12T08:23:11.043Z",
"data": {
"email_id": "re_abc123",
"to": "tu.nguyen@example.com",
"subject": "Welcome to Acme Corp",
"tags": [{ "name": "tenant", "value": "..." }]
}
}Xác minh chữ ký webhook
Webhook của Resend được ký bằng Svix. Xác minh ba header (svix-id, svix-timestamp, svix-signature) với webhook secret của bạn trước khi tin tưởng body.
from svix.webhooks import Webhook, WebhookVerificationError
WEBHOOK_SECRET = "whsec_..." # from your dashboard
def handle_resend_webhook(headers: dict, raw_body: bytes):
try:
wh = Webhook(WEBHOOK_SECRET)
payload = wh.verify(raw_body, headers)
except WebhookVerificationError:
return 401 # signature didn't match — drop it
# payload is now a verified dict
event_type = payload["type"]
...Email inbound (ứng viên phản hồi)
/api/v1/webhooks/resend-inboundCông khaiSự kiện email inbound. Địa chỉ reply-to của Tick Up là duy nhất cho mỗi lần gửi outbound, nên mọi phản hồi đều rơi vào webhook này gắn với cuộc hội thoại gốc.
Khi bạn gửi email qua Tick Up, header Reply-To trỏ tới một địa chỉ một-lần dưới reply.tickup.vn. Bất cứ thứ gì ứng viên gửi lại đều đến đây. Chúng tôi tự động hủy mọi email follow-up đang chờ cho cuộc hội thoại đó ngay khi có phản hồi.
Idempotency
Webhook delivery có thể được thử lại sau khi timeout, nên cùng một sự kiện có thể đến nhiều hơn một lần. Luôn coi handler là idempotent — dùng email_id (Resend) hoặc svix-id của Svix làm khóa dedup trong storage của bạn:
# Postgres example — unique constraint on event_id
INSERT INTO webhook_events (event_id, type, payload, received_at)
VALUES (%s, %s, %s, NOW())
ON CONFLICT (event_id) DO NOTHING;Webhook sự cố (Sentry)
/api/v1/webhooks/sentryCông khaiAlert từ Sentry route vào trình theo dõi issue QC của Tick Up. Endpoint này dành cho pipeline SRE của chúng tôi — đưa vào đây để tham chiếu.
QC Lead Agent của Tick Up nhận alert Sentry, tự tạo issue QC, và kích hoạt health check hàng ngày/hàng tuần. Bạn không cần gọi trực tiếp — nó được nối dây giữa Tick Up và tổ chức Sentry của chúng tôi.
Test webhook cục bộ
Dùng ngrok hoặc Svix Play để tunnel một URL HTTPS công khai vào server phát triển cục bộ. Trỏ Tick Up vào URL tunnel, kích hoạt sự kiện, và bước qua handler bằng debugger thông thường.
Sắp ra mắt
Webhook do khách hàng cấu hình cho thay đổi vòng ứng viên, tạo đơn ứng tuyển, và xác nhận phỏng vấn đang nằm trong roadmap. Nếu tích hợp của bạn cần ngay bây giờ, báo cho chúng tôi tại hello@tickup.vn và chúng tôi sẽ ưu tiên.
Xem lịch sử thay đổi để biết những gì thực sự đã ship.