---
title: "ปลายทาง Webhook"
description: "จัดการ URL ของ webhook หลายรายการด้วยข้อมูลลับและตัวกรองเหตุการณ์สำหรับแต่ละปลายทาง"
---

ระบบ webhook แบบปลายทางช่วยให้คุณลงทะเบียนปลายทางได้ **หลายรายการ**
ต่อองค์กร โดยแต่ละรายการมี secret สถานะ และการสมัครรับข้อมูลสำหรับชุดย่อยของประเภทเหตุการณ์เป็นของตนเอง นี่คือ
รูปแบบที่แนะนำสำหรับการผสานรวมใหม่ทั้งหมด

เปรียบเทียบกับ [webhook URL เดียวแบบเดิม](/api-reference/organizations#legacy-single-url-webhook)
ซึ่งคงไว้เพื่อความเข้ากันได้กับเวอร์ชันก่อนหน้า แต่รองรับเพียงหนึ่ง URL ต่อ
องค์กร

## ปลายทาง

| วิธีการ | พาธ | บทบาทที่ต้องมี | คำอธิบาย |
|--------|------|---------------|-------------|
| `GET` | `/v1/developer/webhook-endpoints` | `admin+` | แสดงรายการปลายทาง |
| `POST` | `/v1/developer/webhook-endpoints` | `admin+` | สร้างปลายทาง |
| `PATCH` | `/v1/developer/webhook-endpoints/{endpoint_id}` | `admin+` | อัปเดตป้ายกำกับ / URL / เหตุการณ์ / สถานะ |
| `DELETE` | `/v1/developer/webhook-endpoints/{endpoint_id}` | `admin+` | ลบปลายทาง |
| `POST` | `/v1/developer/webhook-endpoints/{endpoint_id}/test` | `admin+` | ส่งการจัดส่งทดสอบที่ลงนามแล้ว |
| `GET` | `/v1/developer/webhook-deliveries` | `admin+` | ตรวจสอบผลการจัดส่งปลายทางและแบบเดิมล่าสุด |

## ออบเจ็กต์เอนด์พอยต์

```json
{
  "id": "c4d5e6f7-...",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "agent_id": 42,
  "agent_name": "Support Agent",
  "secret_hint": "a1b2…9f0e",
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z"
}
```

| ฟิลด์ | ประเภท | คำอธิบาย |
|-------|------|-------------|
| `id` | UUID | ID ของเอนด์พอยต์ |
| `label` | string | ชื่อที่แสดง ความยาว 1–120 อักขระ |
| `url` | string | URL แบบ HTTPS อนุญาต `http://localhost` สำหรับการพัฒนา |
| `events` | array of string | ประเภทอีเวนต์ที่สมัครรับ (ดู[ค่าที่ใช้ได้](#valid-event-types)) อาร์เรย์ว่างจะสมัครรับทุกอีเวนต์ ยกเว้นอีเวนต์ต่อเทิร์นที่ต้องระบุอย่างชัดเจน (`telephony.turn` / `web.turn`) |
| `status` | string | `active`, `disabled` (หยุดชั่วคราวด้วยตนเอง) หรือ `failing` (ตั้งค่าอัตโนมัติเมื่อการส่งข้อมูลใช้กำหนดการลองใหม่ 24 ชั่วโมงจนหมดโดยไม่ได้รับ 2xx แม้แต่ครั้งเดียว) |
| `agent_id` | integer \| null | เอเจนต์ที่เอนด์พอยต์นี้กำหนดขอบเขตไว้ `null` หมายถึงทั้งองค์กร |
| `agent_name` | string \| null | ชื่อของเอเจนต์ที่กำหนดขอบเขต หรือ `null` สำหรับเอนด์พอยต์ทั้งองค์กร |
| `secret_hint` | string | อักขระ 4 ตัวแรกและ 4 ตัวสุดท้ายของข้อมูลลับสำหรับการลงนาม พร้อมจุดไข่ปลา (`a1b2…9f0e`) — เพียงพอสำหรับอ้างอิงข้อมูลลับที่คุณบันทึกไว้ในเครื่องโดยไม่เปิดเผยค่าทั้งหมด |
| `created_at`, `updated_at` | timestamp | |

<Note>
  `secret` แบบเต็มของเอนด์พอยต์จะส่งคืน **เพียงครั้งเดียว** เมื่อสร้าง
  และจะไม่ส่งคืนอีก จัดเก็บอย่างปลอดภัย — หากทำหาย ให้ลบเอนด์พอยต์
  และสร้างใหม่
</Note>

### ประเภทอีเวนต์ที่ใช้ได้

`events` จะได้รับการตรวจสอบกับชุดนี้โดยตรง — ค่าที่อยู่นอกเหนือจากรายการ
จะส่งคืน `400` ดู[แค็ตตาล็อกอีเวนต์](/th/webhooks/events)สำหรับ
โครงสร้างเพย์โหลดของแต่ละประเภท

- `telephony.incoming`, `telephony.complete`, `telephony.tool`, `telephony.turn`
- `web.incoming`, `web.complete`, `web.tool`, `web.turn`
- `call.graded`, `call.data_extracted`
- `campaign.completed`
- `issue.reported`, `issue.escalated`
- `test-call.completed`
- `alert.triggered`

`issue.escalated` ไม่มีบริบทเอเจนต์ และจะส่งไปยัง
เอนด์พอยต์ทั้งองค์กรเท่านั้น

ไม่สามารถเลือก `voice.ready` และ `voice.failed` ได้โดยตรง หากต้องการรับ
อีเวนต์เหล่านี้ ให้สร้างเอนด์พอยต์ทั้งองค์กรด้วย `events: []` รายการอีเวนต์ว่าง
จะรับทุกอีเวนต์ที่รองรับ ยกเว้น `telephony.turn` และ `web.turn`
ซึ่งต้องเลือกอย่างชัดเจน

### สถานะเอนด์พอยต์

- `active` — การส่งข้อมูลดำเนินไปตามปกติ
- `disabled` — หยุดชั่วคราวด้วยตนเองผ่าน `PATCH` จะไม่มีการส่งคำขอ เรา
  จะไม่เปลี่ยนสถานะของเอนด์พอยต์ `disabled` เอง การเปลี่ยนกลับเป็น
  `active` เป็นการตัดสินใจของคุณเสมอ
- `failing` — ตั้งค่าอัตโนมัติเมื่อการส่งข้อมูลไปยังเอนด์พอยต์ใช้
  กำหนดการลองใหม่ทั้งหมดจนหมด (8 ครั้งภายใน 24 ชั่วโมง) โดย
  ไม่เคยได้รับ 2xx เอนด์พอยต์ที่ล้มเหลวจะไม่ได้รับทราฟฟิกเพิ่มเติม
  เมื่อแก้ไขเอนด์พอยต์แล้ว ให้ `PATCH` สถานะกลับเป็น `active`
  การส่งข้อมูลที่กำหนดการลองใหม่ยังไม่หมดจะดำเนินต่อจากจุดที่หยุดไว้

---

## แสดงรายการเอนด์พอยต์

<CodeGroup>
```bash cURL
curl https://api.thunderphone.com/v1/developer/webhook-endpoints \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

ส่งคืนอาร์เรย์ของ[ออบเจ็กต์เอนด์พอยต์](#endpoint-object)
ส่ง `?agent_id=42` เพื่อส่งคืนเฉพาะเอนด์พอยต์ที่กำหนดขอบเขตไว้สำหรับเอเจนต์นั้น

### เอนด์พอยต์ที่กำหนดขอบเขตตามเอเจนต์

เอนด์พอยต์ทั้งองค์กรจะรับทุกอีเวนต์ที่ตรงกัน เอนด์พอยต์ที่มี
`agent_id` จะรับเฉพาะอีเวนต์ที่ตรงกันสำหรับการโทรที่เอเจนต์นั้นจัดการ
อีเวนต์ที่ไม่มีบริบทเอเจนต์ เช่น `alert.triggered` จะไม่ส่งไปถึงเอนด์พอยต์นี้ คุณ
ยังสามารถสร้างและจัดการเอนด์พอยต์เหล่านี้ได้จากส่วน
**เว็บฮุค** ของตัวสร้างเอเจนต์

---

## สร้างปลายทาง

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label":  "Production — Call events",
    "url":    "https://example.com/thunderphone/hook",
    "events": ["telephony.incoming", "telephony.complete"]
  }'
```

```python Python
result = requests.post(
    "https://api.thunderphone.com/v1/developer/webhook-endpoints",
    headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
    json={
        "label":  "Production — Call events",
        "url":    "https://example.com/thunderphone/hook",
        "events": ["telephony.incoming", "telephony.complete"],
    },
).json()
secret = result["secret"]
endpoint_id = result["id"]
```
</CodeGroup>

### ฟิลด์คำขอ

| ฟิลด์ | ประเภท | จำเป็น | คำอธิบาย |
|-------|------|----------|-------------|
| `label` | สตริง | ใช่ | 1–120 อักขระ |
| `url` | สตริง | ใช่ | URL แบบ HTTPS (`http` อนุญาตเฉพาะสำหรับ `localhost` / `127.0.0.1`) |
| `events` | อาร์เรย์ | ไม่ | ว่างเปล่าหรือไม่ระบุจะสมัครรับทุกอีเวนต์ ยกเว้น `telephony.turn` / `web.turn` ซึ่งต้องสมัครรับอย่างชัดเจน ต้องใช้ค่าที่ระบุใน [ประเภทอีเวนต์ที่ใช้ได้](#valid-event-types) ระบบจะลบค่าที่ซ้ำกัน |
| `agent_id` | จำนวนเต็ม \| null | ไม่ | จำกัดการส่งไปยังเอเจนต์ในองค์กรนี้ ไม่ต้องระบุหรือใช้ `null` สำหรับปลายทางระดับทั้งองค์กร |

ส่งคืน `201 Created` พร้อม [ออบเจ็กต์ปลายทาง](#endpoint-object) ที่อัปเดตแล้ว และมีฟิลด์ `secret` ระดับบนสุดเพิ่มเติมซึ่งมีคีย์สำหรับลงนามแบบดิบ — สตริงเลขฐานสิบหก 48 อักขระ:

```json
{
  "id": "c4d5e6f7-…",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "secret_hint": "a1b2…9f0e",
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z",
  "secret": "a1b2c37e08d94f5b16a2c8d90e7f3a4b5c6d7e8f90a19f0e"
}
```

<Warning>
  ระบบส่งคืน `secret` **เฉพาะตอนสร้างเท่านั้น** การตอบกลับ `GET` ครั้งถัดไป
  จะมีเพียง `secret_hint` คัดลอกค่าทั้งหมดไปยังตัวจัดการข้อมูลลับ
  ก่อนปิดการตอบกลับ
</Warning>

---

## อัปเดตปลายทาง

<CodeGroup>
```bash cURL
curl -X PATCH https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-... \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label":  "Production — Call + Grade events",
    "events": ["telephony.incoming", "telephony.complete", "call.graded"]
  }'
```
</CodeGroup>

| ฟิลด์ | ประเภท | คำอธิบาย |
|-------|------|-------------|
| `label` | สตริง | |
| `url` | สตริง | |
| `events` | อาร์เรย์ | |
| `status` | สตริง | `active` หรือ `disabled` ตั้งค่าเป็น `active` เพื่อเปิดใช้งานปลายทางอีกครั้งเมื่อเซิร์ฟเวอร์ทำเครื่องหมายเป็น `failing` |
| `agent_id` | จำนวนเต็ม \| null | ตั้งค่า ID เอเจนต์เพื่อจำกัดขอบเขตปลายทาง หรือใช้ `null` เพื่อให้เป็นระดับทั้งองค์กร |

ส่งคืน `200 OK` พร้อม [ออบเจ็กต์ปลายทาง](#endpoint-object) ที่อัปเดตแล้ว

---

## ส่งการนำส่งทดสอบ

ส่งเหตุการณ์ `webhook.test` แบบสังเคราะห์ไปยังปลายทางหนึ่งรายการผ่านไปป์ไลน์การนำส่งตามปกติ ซึ่งรวมถึงการซีเรียลไลซ์ JSON แบบมาตรฐาน `X-ThunderPhone-Signature` การบันทึกการนำส่ง และการติดตามการลองใหม่
การทดสอบจะกำหนดเป้าหมายไปยังปลายทางที่เลือกโดยไม่คำนึงถึงตัวกรอง `events`

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../test \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

ปลายทางจะได้รับเอนเวโลปดังนี้:

```json
{
  "data": {
    "message": "ThunderPhone webhook test",
    "sent_at": "2026-07-17T20:12:34.567890+00:00"
  },
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "type": "webhook.test"
}
```

API จะส่งคืน `200 OK` หลังการลองครั้งแรก แม้ว่าปลายทางจะส่งคืนข้อผิดพลาด
ตรวจสอบ `success` `status` `response_code` และ `error` เพื่อดูผลลัพธ์ของการนำส่ง:

```json
{
  "success": true,
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "event_type": "webhook.test",
  "status": "delivered",
  "response_code": 204,
  "error": ""
}
```

`webhook.test` เป็นเหตุการณ์สังเคราะห์และไม่สามารถเพิ่มลงในการสมัครรับ `events` ของปลายทางได้
หากการลองครั้งแรกล้มเหลว การนำส่งจะใช้กำหนดการลองใหม่เดียวกับการนำส่งเหตุการณ์ปกติ

หากต้องการกำหนดค่าทริกเกอร์โดยอ้างอิงโครงสร้างของเหตุการณ์จริง ให้ส่ง `event_type` ที่ไม่บังคับ
การนำส่งยังคงเป็นแบบสังเคราะห์และมี `"sample": true`; ตัวอย่างที่เกี่ยวข้องกับการโทรจะใช้ `call_id: 0` และ `agent_id: 0`

```bash
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../test \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event_type":"call.graded"}'
```

`event_type` รับค่าใดก็ได้จาก[ประเภทเหตุการณ์ที่ใช้ได้](#valid-event-types)
การไม่ระบุค่านี้จะคงพฤติกรรม `webhook.test` แบบทั่วไปไว้

---

## ลบปลายทาง

<CodeGroup>
```bash cURL
curl -X DELETE https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-... \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

ส่งคืน `204 No Content` การนำส่งไปยัง URL จะหยุดทันที
การลองใหม่ที่กำลังดำเนินการอยู่จะถูกยกเลิก

---

## ดีบักการนำส่ง

ก่อนสรุปว่าไม่ได้ส่ง webhook ให้ตรวจสอบ
[`GET /v1/developer/webhook-deliveries`](/api-reference/webhook-deliveries)
โดยจะแสดงการลองล่าสุดจากระบบ webhook ทั้งสองระบบ รวมถึงรหัสการโทร ต้นทาง URL สถานะ HTTP จำนวนครั้งที่ลอง หมวดหมู่ความล้มเหลวที่อนุญาต และเวลาลองใหม่ครั้งถัดไป
จะไม่ส่งคืนเพย์โหลดเหตุการณ์ ทรานสคริปต์ ข้อความข้อผิดพลาดที่จัดเก็บ เนื้อหาการตอบกลับ หรือพาธ URL

คุณยังดูประวัติล่าสุดเดียวกันได้ที่ **เอเจนต์ → เลือกเอเจนต์ → Webhooks →
การนำส่งล่าสุด** แถวจะแสดงป้ายกำกับปลายทางและต้นทาง URL ที่ใช้ในการลองล่าสุด
นี่คือสถานะการดำเนินงาน ไม่ใช่บันทึกการตรวจสอบถาวร การลบปลายทางจะลบแถวการนำส่งของปลายทางนั้นด้วย

สำหรับ `404` ของ n8n ให้ยืนยันก่อนว่าเวิร์กโฟลว์ทำงานอยู่ รับ `POST` และใช้ URL ของ webhook สำหรับการใช้งานจริงแทน URL ทดสอบ
`401` หรือ `403` บ่งชี้ปัญหาการตรวจสอบสิทธิ์หรือการตรวจสอบลายเซ็น ส่วนการหมดเวลาบ่งชี้ความหน่วงหรือความพร้อมใช้งานของปลายทาง และข้อผิดพลาด TLS บ่งชี้ปัญหาห่วงโซ่ใบรับรอง ชื่อโฮสต์ หรือวันหมดอายุ

---

## ที่เกี่ยวข้อง

<CardGroup cols={2}>
  <Card title="แค็ตตาล็อกเหตุการณ์" icon="list" href="/th/webhooks/events">
    รายการค่า `events` ทั้งหมดที่คุณสามารถสมัครรับได้
  </Card>
  <Card title="ภาพรวม Webhooks" icon="bolt" href="/th/webhooks/overview">
    การตรวจสอบลายเซ็นและความหมายของการนำส่ง
  </Card>
</CardGroup>
