GET /v1/events
GET /v1/events/{event_id}事件是賬戶上發生的事實,Webhook 只是把它告訴你的一次嘗試。兩者分開的好處很實際:接收端宕機一整天、重試全部耗盡,甚至壓根沒配置過端點,事件都還在。
列表
除 通用列表參數 外:
| 參數 | 説明 |
|---|---|
type | 事件類型,見 Webhook |
reference_id | 事件主體的單號:訂單號 / 退款號 / 拒付號 |
# 拉回昨天所有支付成功事件
curl -G "https://api.kukopay.com/v1/events" \
-H "X-Api-Key: kuko_live_你的密鑰" \
-d type=payment.succeeded \
-d "created[gte]=2026-09-20T00:00:00Z" \
-d "created[lte]=2026-09-20T23:59:59Z" \
-d limit=100單個事件
收到 Webhook 但當時沒能處理完時,用事件 id 從源頭重新取一次,而不是信任本地緩存的報文。
curl "https://api.kukopay.com/v1/events/evt_3f2a9c7e1b4d0568a2cf" \
-H "X-Api-Key: kuko_live_你的密鑰"響應
{
"object": "event",
"id": "evt_3f2a9c7e1b4d0568a2cf",
"type": "payment.succeeded",
"mode": "live",
"created_at": "2026-09-21T08:31:12.114Z",
"data": {
"object": {
"object": "order",
"trade_no": "TRD_9F3A2C7E...",
"out_trade_no": "ORD_20260921_0001",
"amount": 2990,
"status": "paid"
}
}
}data.object 與對應查詢接口返回的對象完全一致,也與 Webhook 報文裏的一致——一套解析代碼通用。
事件 id 由事件類型和主體單號推導而來,是確定性的。同一筆訂單的 payment.succeeded 無論被多少條路徑觸發,都只會產生一個事件,所以按 id 去重是可靠的。
典型用法:補齊漏掉的事件
// 接收端恢復後,把宕機窗口內的事件補回來
async function backfill(since, until) {
let startingAfter
while (true) {
const query = new URLSearchParams({
limit: "100",
"created[gte]": since,
"created[lte]": until,
})
if (startingAfter) query.set("starting_after", startingAfter)
const res = await fetch(
`https://api.kukopay.com/v1/events?${query}`,
{ headers: { "X-Api-Key": process.env.KUKOPAY_API_KEY } }
)
const { data: page } = await res.json()
for (const event of page.data) {
// 與 Webhook 走同一個處理函數,按 event.id 去重
await handleEvent(event)
}
if (!page.has_more) return
startingAfter = page.data[page.data.length - 1].id
}
}事件按創建時間倒序返回,所以補數據時用 created[gte] / created[lte] 圈定窗口,比依賴游標從頭翻更省事。