---
url: https://docs.nemo12.com/reference/webhooks.md
description: >-
  Webhooks và tích hợp ngoài: Nemo12 hiện không có webhook nào, và những thứ dễ
  nhầm là webhook nhưng không phải.
---

# Webhooks & tích hợp ngoài

## Trạng thái hiện tại

**Nemo12 không có webhook nào** — không nhận vào, không gửi ra.

Rất dễ nhầm hai thứ dưới đây là webhook, nên nói rõ:

| Thứ | Là gì | Vì sao **không** phải webhook |
| --- | --- | --- |
| `POST /v1/auth/google` | App gửi ID token của Google lên để đổi lấy session | Client chủ động gọi API của ta. Google không gọi ngược vào hệ thống. |
| `nemo12-events` | Queue nội bộ | Không rời khỏi Cloudflare account, không có HTTP endpoint ([queues](queues.md)) |

Nghĩa là **hiện không có bề mặt HTTP nào nhận lệnh từ bên thứ ba**. Đây là một tài sản an ninh — mất nó phải có lý do xứng đáng.

***

## Tích hợp ngoài đang thật sự có

| Dịch vụ | Chiều | Cách dùng |
| --- | --- | --- |
| Google Identity | Ra → vào theo request | Xác minh ID token khi đăng nhập (`GOOGLE_CLIENT_ID` trong vars) |
| Cloudflare AI Gateway `nemo12` | Ra | Mọi lời gọi LLM ([ai-registry](ai-registry.md)) |
| Cloudflare Access | Trước API | Bảo vệ surface nội bộ ở tầng hạ tầng, không phải code |

***

## Khi nào sẽ cần webhook

| Tình huống | Chiều |
| --- | --- |
| Thanh toán / gia hạn gói | Nhận vào |
| Email/push (delivery, bounce, unsubscribe) | Nhận vào |
| Trạng thái job crawl đề chạy ngoài (SDD-014) | Nhận vào |
| Bắn sự kiện học tập sang hệ thống của trường đối tác | Gửi ra |

## Luật bắt buộc khi thêm webhook

### Nhận vào

1. **Xác thực chữ ký, không xác thực bằng IP.** HMAC theo secret trong Cloudflare Secrets — không bao giờ trong `vars` hay code (QG-008).
2. **Chống replay** — kiểm timestamp, từ chối request cũ hơn 5 phút.
3. **Idempotent theo id của bên gửi.** Provider nào cũng gửi lại.
4. **Trả 2xx nhanh, xử lý sau.** Nhận → validate → đẩy vào queue → trả 200. Không xử lý nặng trong request webhook.
5. **Đường đi riêng** `/v1/hooks/{provider}` — **không** dùng chung middleware session; đây không phải người dùng đăng nhập.
6. **Payload là dữ liệu, không phải lệnh.** Không bao giờ tin trường `role`, `learner_id`, `amount` từ bên ngoài mà không kiểm chứng lại với nguồn sự thật của chính mình.
7. **Ghi audit log** mọi lần nhận (QG-008).

### Gửi ra

1. **Chỉ gửi tới URL đã đăng ký sẵn**, không bao giờ gửi tới URL lấy từ dữ liệu người dùng (chống SSRF).
2. **Ký payload** để bên nhận xác minh được.
3. **Không gửi dữ liệu trẻ em ra ngoài khi chưa có consent của phụ huynh** (REQ-SEC — child data minimization).
4. **Retry có backoff + DLQ**, không retry vô hạn.
5. Khai vào bảng ở trang này trong cùng PR.

## Trace

* REQ-SEC-06 (CORS/CSRF), QG-008 (security & privacy), QG-009 (reliability).
* Thiết kế: [SDD-001](../architecture/sdd-001-platform.md) §6, [SDD-006](../architecture/sdd-006-reliability.md) §11.
