Chuyển tới nội dung chính

Webhook

Webhook để GADS đẩy dữ liệu ra endpoint của đối tác khi có sự kiện trong chiến dịch. Automation Hook API để hệ thống bên ngoài gọi vào GADS và đưa dữ liệu vào workflow theo thời gian thực. Trang này mô tả cấu hình trên Back Office (BO), quy tắc schema JSON, cách gửi request và cấu trúc response.

Tổng quan

  • Nhận dữ liệu người dùng từ hệ thống bên ngoài và kích hoạt workflow ngay.
  • Gửi một object JSON hoặc mảng nhiều object trong một HTTP request.
  • Hỗ trợ điều kiện trong workflow theo các trường trong payload.
  • Action trong workflow có thể ánh xạ nội dung từ các trường đã gửi.

API Webhook

MụcGiá trị
Endpoint/api/automation/hook/{workflowId}
Xác thựcHeader X-Hook-Secret
PayloadMột object JSON hoặc array<object>
Trường bắt buộc tối thiểuphone

Automation Hook API cho phép hệ thống bên ngoài gửi dữ liệu trực tiếp vào workflow. Mỗi workflow gắn hook có một URL riêng, xác định bởi workflowId trong đường dẫn.

Quy tắc vận hành V1

  • Chỉ hỗ trợ POST.
  • Trên BO, schema khai báo cho một object.
  • Máy chủ nhận body là object đơn hoặc array<object> (batch).
  • Máy chủ ánh xạ (resolve) người dùng chủ yếu theo phone và có thể tự tạo bản ghi người dùng nếu chưa tồn tại.
URL production mẫu
https://cdp.b4444.cc/api/automation/hook/{workflowId}

Các khái niệm chính

Khái niệmMô tả
workflowIdĐịnh danh workflow có kích hoạt hook; mỗi workflow một URL.
X-Hook-SecretChuỗi bí mật xác thực request tới đúng workflow.
phoneTrường tối thiểu để ánh xạ hoặc tạo người dùng (V1).
nameTên hiển thị; dùng làm tên người dùng và trong bước ánh xạ workflow.

Cấu hình

Trên BO, workflow dùng trigger Webhook được cấu hình trong một panel. BO V1 gọn cho vận hành; phía tích hợp cần URL hook, secret và schema đã được cấu hình sẵn.

Thành phần giao diện

Thành phần UIMô tảĐối tượng
Webhook URLURL cố định theo workflow; client gọi đúng URL này.Vận hành, đối tác tích hợp
Webhook SecretChuỗi bí mật do hệ thống tạo khi lưu workflow lần đầu; BO cho phép sao chép.Vận hành, đối tác tích hợp
Schema FieldsKhai báo trường: tên, kiểu dữ liệu, bắt buộc hay không.Vận hành
Xem schema & ví dụXem trước JSON Schema, payload mẫu (một object và batch).Vận hành, đối tác tích hợp

Ví dụ cấu hình

Webhook URL:

https://cdp.b4444.cc/api/automation/hook/500

Webhook Secret:

evs_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

Schema Fields mẫu

Tên trườngKiểuBắt buộcGhi chú
phonestringTrường hệ thống
namestringTùy workflow (có hoặc không)Trường nghiệp vụ thường gặp
voucherCodestringKhôngTrường tùy chỉnh do vận hành thêm

Schema và Fields

Trên BO V1, schema khai báo cho một đối tượng. Phía máy chủ áp dụng cùng schema cho:

  • Yêu cầu đơn lẻ: { ... }
  • Batch: [{ ... }, { ... }]

Quy tắc schema

  • Schema gốc phải có kiểu object.
  • Chỉ hỗ trợ trường phẳng (flat); chưa hỗ trợ object lồng nhau (nested) hay mảng object lồng trong trường.
  • Kiểu được hỗ trợ: string, number, boolean.
  • phone là trường hệ thống bắt buộc, không xóa khỏi schema.
  • Mỗi trường có thể Required hoặc không.

Tên trường không được sử dụng

Các tên sau được hệ thống dành cho runtime; không dùng làm tên trường nghiệp vụ trong schema:

Trường hệ thống (nhóm 1)Trường hệ thống (nhóm 2)
hookpayload
valueentrySource
eventSourceeventType
hookWorkflowIdhookMethod
hookReceivedAthookIndex

Ví dụ schema object

{
"type": "object",
"properties": {
"phone": { "type": "string" },
"name": { "type": "string" },
"voucherCode": { "type": "string" },
"totalAmount": { "type": "number" },
"isVip": { "type": "boolean" }
},
"required": ["phone"]
}
mẹo

Nếu workflow cần lọc hoặc ánh xạ theo một trường, hãy khai báo trường đó trong schema để BO hiển thị trong điều kiện và bước ánh xạ (mapping).

Gửi yêu cầu API

Headers

HeaderBắt buộcMô tả
Content-Type: application/jsonBody là JSON.
X-Hook-SecretSecret của workflow; sai trả 401 Unauthorized.
X-Idempotency-KeyKhuyến nghịKhóa idempotency; nên duy nhất theo từng thao tác nghiệp vụ.

Gửi 1 object

curl -X POST "https://cdp.b4444.cc/api/automation/hook/500" \
-H "Content-Type: application/json" \
-H "X-Hook-Secret: evs_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Idempotency-Key: order-20260323-0001" \
-d '{
"phone": "0389151977",
"name": "Karis",
"voucherCode": "VC001",
"totalAmount": 250000,
"isVip": true
}'

Gửi batch nhiều object

curl -X POST "https://cdp.b4444.cc/api/automation/hook/500" \
-H "Content-Type: application/json" \
-H "X-Hook-Secret: evs_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Idempotency-Key: batch-20260323-0001" \
-d '[
{
"phone": "0389151977",
"name": "Karis",
"voucherCode": "VC001"
},
{
"phone": "0901234567",
"name": "Lan",
"voucherCode": "VC002"
}
]'

Quy tắc payload

  • Body là một object → kích hoạt xử lý workflow một lần cho payload đó.
  • Body là array<object>fan-out: xử lý từng phần tử như một payload riêng.
  • Mỗi phần tử trong batch phải thỏa schema đã khai báo trên BO.
  • Nếu schema bắt buộc phone thì mọi phần tử trong mảng đều phải có phone.

Idempotency và khử trùng lặp (dedupe)

Hook có cơ chế chống xử lý trùng — cần thiết khi client có retry tự động.

Khi có header X-Idempotency-Key

  • Máy chủ dùng giá trị key làm cơ sở khử trùng.
  • Gửi lại cùng body và cùng key → bị coi là trùng (deduped), không xử lý lại như request mới.
  • Cùng nội dung nhưng cần chạy lại như lần đầu → phải đổi giá trị key.

Khi không có X-Idempotency-Key

  • Hệ thống fall back sang băm (hash) nội dung payload.
  • Gửi lại đúng cùng payload có thể vẫn bị khử trùng.
  • Môi trường production: luôn gửi X-Idempotency-Key.
Khuyến nghị tích hợp

Mỗi thao tác nghiệp vụ dùng một X-Idempotency-Key duy nhất (ví dụ: mã đơn, mã giao dịch, UUID sự kiện nguồn).

Kết quả trả về

Response thành công

Cấu trúc bọc (envelope) chung:

{
"status": 1,
"message": "Gửi thành công",
"data": { ... }
}

Trường trong data

TrườngKiểuMô tả
workflowIdnumberĐịnh danh workflow nhận hook.
partnerIdstringĐối tác sở hữu workflow.
triggerTypestringLoại kích hoạt; V1 là hook.
methodstringPhương thức HTTP đã nhận; V1 là POST.
urlstringURL mà máy chủ ghi nhận cho request.
receivedCountnumberSố object trong payload; với batch bằng số phần tử mảng.
enqueuednumberSố phần tử đưa vào hàng đợi (enqueue) thành công.
dedupednumberSố phần tử trùng, không đưa vào hàng đợi lại.
skippednumberSố phần tử bỏ qua (ví dụ không khớp audience).
rejectednumberSố phần tử từ chối khi phân phối xử lý.
hookConfigobjectSiêu dữ liệu cấu hình hook tại thời điểm xử lý (hỗ trợ kiểm tra).
itemsarrayKết quả chi tiết theo từng phần tử.

Trường trong data.hookConfig

TrườngMô tả
enabledHook đang bật và nhận request hay không.
secretConfiguredWorkflow đã được gán secret hay chưa.
phoneFieldTên trường ánh xạ người dùng theo số điện thoại.
userIdFieldTrường tương thích; V1 ưu tiên phone.
idByOaFieldTrường tương thích; V1 ưu tiên phone.
fullNameFieldTrường họ tên, thường là name.
autoCreateUserTự tạo người dùng nếu chưa ánh xạ được.
dedupeHeaderTên header idempotency, mặc định X-Idempotency-Key.
dedupeFieldTrường trong payload dùng khử trùng nếu cấu hình; V1 mặc định không dùng.
payloadQueryParamTên tham số query khi gửi payload qua URL; V1 là payload.
methodsDanh sách phương thức HTTP cho phép; V1 là ["POST"].
schemaJSON Schema object áp dụng tại thời điểm request.

Trường trong data.items[]

TrườngMô tả
indexChỉ số phần tử (bắt đầu từ 0); payload một object thường chỉ có 0.
outcomeMột trong: enqueued, deduped, skipped, rejected.
messageMô tả ngắn kết quả xử lý.
userIdĐịnh danh người dùng đã ánh xạ cho phần tử.
statusIdID trạng thái trên hàng đợi khi outcomeenqueued.

Ví dụ response — enqueued

{
"status": 1,
"message": "Gửi thành công",
"data": {
"workflowId": 500,
"partnerId": "kimnguyenbao",
"triggerType": "hook",
"method": "POST",
"url": "https://cdp.b4444.cc/api/automation/hook/500",
"receivedCount": 1,
"enqueued": 1,
"deduped": 0,
"skipped": 0,
"rejected": 0,
"hookConfig": {
"enabled": true,
"secretConfigured": true,
"phoneField": "phone",
"fullNameField": "name",
"autoCreateUser": true,
"dedupeHeader": "X-Idempotency-Key",
"methods": ["POST"],
"schema": {
"type": "object",
"properties": {
"phone": { "type": "string" },
"name": { "type": "string" }
},
"required": ["phone"]
}
},
"items": [
{
"index": 0,
"outcome": "enqueued",
"message": "queued",
"userId": "188986237",
"statusId": 6734
}
]
}
}

Ví dụ response — deduped

{
"status": 1,
"message": "Gửi thành công",
"data": {
"workflowId": 500,
"receivedCount": 1,
"enqueued": 0,
"deduped": 1,
"skipped": 0,
"rejected": 0,
"items": [
{
"index": 0,
"outcome": "deduped",
"message": "duplicate skipped",
"userId": "188986237"
}
]
}
}

Response lỗi (HTTP 4xx / 5xx)

{
"status": 0,
"message": "..."
}

Bảng mã HTTP và ngữ cảnh

HTTP statusNgữ cảnhVí dụ message
400Workflow không hợp lệ, triggerConfig sai, JSON không hợp lệ, payload không khớp schemaPayload không hợp lệ tại $.phone: thiếu field bắt buộc
401X-Hook-Secret sai hoặc thiếuSai secret của workflow hook.
403Hook tạm tắtWorkflow hook đang bị tắt.
404Không tồn tại workflowIdKhông tìm thấy workflow.
405Phương thức khác POST (hoặc không nằm trong methods)HTTP method không được phép cho workflow hook này.
409Workflow chưa published hoặc chưa có bước bắt đầu hợp lệWorkflow chưa ở trạng thái published.
500Lỗi máy chủ nội bộLỗi: ...

Ví dụ lỗi sai secret

{
"status": 0,
"message": "Sai secret của workflow hook."
}

Ví dụ lỗi schema

{
"status": 0,
"message": "Payload không hợp lệ tại $.phone: thiếu field bắt buộc"
}