Khái niệm cốt lõi

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)

POST/api/v1/webhooks/resendCông khai

Endpoint 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ệnKhi nào kích hoạt
email.deliveredMail server của người nhận đã chấp nhận tin.
email.openedNgười nhận đã load pixel theo dõi.
email.clickedNgười nhận đã click vào link được theo dõi.
email.bouncedMail server từ chối tin (bounce cứng hoặc mềm).
email.complainedNgười nhận đã đánh dấu email là spam.
email.failedGửi thất bại trước khi đến hàng đợi outbound của Resend.
json
{
  "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)

POST/api/v1/webhooks/resend-inboundCông khai

Sự 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:

python
# 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)

POST/api/v1/webhooks/sentryCông khai

Alert 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.