# Webhook phiên âm báo khi job hoàn tất hoặc thất bại

> Thêm webhook phiên âm bằng webhook_url để nhận POST có chữ ký khi job hoàn tất hoặc thất bại, không phải liên tục hỏi trạng thái.

Canonical: https://transcript1.com/vi/features/webhook-phien-am
Language: vi
Last updated: 2026-10-19

Webhook phiên âm giúp ứng dụng chờ thông báo thay vì liên tục gọi API hỏi trạng thái. Thêm webhook_url khi tạo job; transcript1 gửi POST có chữ ký khi xử lý hoàn tất hoặc thất bại. Khi nhận sự kiện hoàn tất, bạn lấy transcript bằng id.

- transcription.completed và transcription.failed
- Mỗi lần gửi đều có chữ ký HMAC-SHA256
- Tối đa 6 lần gửi, tăng dần thời gian chờ

## Nhận sự kiện trước, lấy nội dung sau

### Hai sự kiện cần xử lý

transcription.completed báo đã có transcript; transcription.failed báo xử lý thất bại. Nếu bạn hủy job, không có webhook.

### Kiểm tra ai gửi request

Header X-Transcript1-Signature có timestamp và chữ ký HMAC-SHA256 của raw body, dùng secret whsec_ của team.

### Có gửi lại khi chưa nhận được

Phản hồi 2xx xác nhận đã nhận. Nếu không, hệ thống chờ lần lượt 2, 4, 8, 16, 32 phút rồi gửi lại, tối đa 6 lần tính cả lần đầu.

### Endpoint phải công khai và dùng HTTPS

Địa chỉ được kiểm tra khi tạo job và trước mỗi lần gửi. Không dùng localhost hoặc URL chuyển hướng.

### Payload không chứa toàn bộ transcript

Sự kiện gửi đối tượng transcription không kèm nội dung transcript. Dùng id để lấy văn bản ở định dạng ứng dụng cần.

## Thêm webhook\_url ngay trong request

Bạn dùng webhook_url khi gửi link, tạo upload từng phần hoặc làm form field khi tải file một lần. Không ghép với reuse_recent. Xem [tham số webhook](https://transcript1.com/vi/docs/webhooks#set-a-webhook-url) trước khi tích hợp.

Webhook phù hợp với các việc chạy nền như xử lý phỏng vấn, lập kho podcast hoặc lấy transcript từ danh sách video. Lưu id của transcription cùng job trong hệ thống của bạn để callback về đúng lần thao tác của người dùng.

Dùng URL HTTPS công khai cuối cùng, không qua chuyển hướng. localhost không nhận được webhook. Ví dụ bên dưới dùng file tải lên để bạn thử toàn bộ luồng bằng một bản ghi mình có quyền sử dụng.

### Tải file và đăng ký nhận webhook

```
curl -X POST "https://api.transcript1.com/v1/transcriptions" \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
  -F file=@episode.mp3 \
  -F webhook_url=https://example.com/hooks/transcript1
```

## Nhận lại cùng sự kiện cũng chỉ xử lý một lần

data chứa đối tượng transcription nhưng không chứa transcript. Ghép data.id với type để nhận biết bản gửi trùng, rồi [lấy transcript qua API](https://transcript1.com/vi/docs/api-reference#get-a-transcription) bằng id.

Một sự kiện có thể tới nhiều lần. Handler đã làm xong nhưng trả lời sau giới hạn 10 giây thì hệ thống vẫn có thể gửi lại. Sau khi kiểm tra chữ ký, lưu sự kiện hoặc đưa vào hàng đợi bền vững rồi trả 2xx sớm. Lưu khóa chống trùng trước khi đăng nội dung hay thông báo cho người dùng.

Tác vụ chạy nền dùng data.id để lấy transcript. Với transcription.failed, đọc data.error và cập nhật trạng thái job của bạn. Nếu hủy job, code xử lý hủy phải tự cập nhật trạng thái vì sẽ không có callback.

### POST gửi đến URL của bạn

```
X-Transcript1-Signature: t=<unix seconds>,v1=<hex digest>

{
  "type": "transcription.completed",
  "created_at": "2026-10-13T09:30:04.000Z",
  "data": {
    "id": "tr_8fK2Lm0PqRsTuVwXyZaBcD",
    "object": "transcription",
    "status": "completed",
    "transcript_source": "speech_to_text",
    "billed_minutes": 4,
    "error": null
  }
}
```

## Xác minh chữ ký webhook HMAC trước khi đọc JSON

Tính HMAC-SHA256 cho chuỗi t + dấu chấm + raw body bằng secret whsec_ của team. So sánh trong thời gian cố định và từ chối timestamp quá xa hiện tại. [Hướng dẫn xác minh](https://transcript1.com/vi/docs/webhooks#verify-the-signature) có ví dụ đầy đủ.

Đọc body nguyên trạng trước khi JSON parser xử lý. Parse rồi ghép JSON lại có thể đổi khoảng trắng hoặc thứ tự key, làm chữ ký không còn khớp. Kiểm tra header, timestamp và độ dài digest; chỉ parse nội dung sau khi chữ ký hợp lệ.

Đoạn Node.js dưới đây giả định t và v1 đã được tách và kiểm tra. Tài liệu có ví dụ đầy đủ cho Node.js và Python với độ lệch timestamp tối đa 5 phút. Dùng toàn bộ secret, gồm cả tiền tố whsec_. Đổi secret của team sẽ áp dụng ngay cho những lần gửi tiếp theo.

### Node.js

```
const expected = crypto
  .createHmac('sha256', secret)
  .update(`${t}.${rawBody}`)
  .digest('hex');
const valid = v1.length === expected.length
  && crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
```

- [Ví dụ kiểm tra chữ ký đầy đủ](https://transcript1.com/vi/docs/webhooks)

## Thử cả sự kiện lỗi và sự kiện trùng

Kiểm tra handler với job hoàn tất, job thất bại và cùng sự kiện gửi lại. Một job hoàn tất không được làm nội dung xuất bản hai lần. Job thất bại không được đi vào luồng lấy và đăng transcript khi chưa có văn bản.

Tách lỗi chữ ký khỏi lỗi xử lý ứng dụng. Mỗi lần gửi chỉ chờ 10 giây, nên đừng đợi lập chỉ mục hay gọi mô hình AI xong mới phản hồi. Hàng đợi của bạn cần tự thử lại các bước phía sau; lịch gửi lại webhook không thay thế việc đó.

Phản hồi không phải 2xx, lỗi kết nối hoặc timeout đều dẫn đến gửi lại sau 2, 4, 8, 16, 32 phút, tổng cộng tối đa 6 lần. Hệ thống không đi theo chuyển hướng. Ghi log id, loại sự kiện và tình trạng nhận; không ghi signing secret.

Nếu đã hết lượt gửi, [đọc lại job qua API](https://transcript1.com/vi/docs/api-reference#get-a-transcription) để đối chiếu trạng thái. Vì vậy, phải lưu id ngay từ lúc tạo; đừng chỉ dựa vào callback để biết một job có tồn tại hay không.

## Câu hỏi thường gặp

### Tôi lấy signing secret ở đâu?

Mở trang “Webhooks” trong bảng điều khiển. Secret bắt đầu bằng whsec_, dùng chung cho team và có thể đổi tại đó bất cứ lúc nào.

### Webhook gửi không thành công thì sao?

Hệ thống tăng dần thời gian chờ và thử tối đa 6 lần trong khoảng một giờ, tính cả lần đầu. Mỗi lần chờ tối đa 10 giây và không đi theo URL chuyển hướng.

### Tôi dùng webhook qua MCP được không?

Không. Webhook chỉ có trong REST API. Công cụ MCP chờ xử lý trong thời gian giới hạn hoặc trả id để đọc lại sau.

## Đọc thêm

- [Webhook (tài liệu)](https://transcript1.com/vi/docs/webhooks)
- [API cho file audio, video](https://transcript1.com/vi/features/speech-to-text-api)
- [AI agent và LLM](https://transcript1.com/vi/use-cases/transcript-cho-ai-agent)
