โปรโตคอล v1
ทุก route, header, body, รหัส outcome และกฎการ retry ของ remote plugin protocol ปลั๊กอินคือ service ที่ deploy แยกต่างหาก: มันสื่อสารกับ Dee Wan ผ่าน HTTP และไม่รันโค้ดใดภายใน Dee Wan ดูเพิ่มเติมที่ การเขียนปลั๊กอิน สำหรับปลั๊กอินแรกตั้งแต่ต้นจนจบ, ความปลอดภัยของปลั๊กอิน สำหรับขอบเขตความเชื่อถือ และ การทดสอบปลั๊กอิน สำหรับวิธีทดสอบปลั๊กอิน
เวอร์ชันของ protocol ที่รองรับ: 1 เวอร์ชันจะถูกตกลงกันครั้งเดียวตอนติดตั้ง และถูก pin ไว้กับ
การติดตั้งปลั๊กอินรายการนั้น การอัปเกรดที่จะเปลี่ยนเวอร์ชันนี้จะถูกปฏิเสธ
(protocol_changed): การย้าย installation ไปยัง v2 หมายถึงการถอนการติดตั้งแล้วติดตั้ง release
ใหม่ การเปลี่ยนแปลงที่ breaking ต่อ route, ความหมาย หรือรหัส error
ต้องใช้ protocol v2 ฟิลด์ใน response ที่เพิ่มเข้ามาได้รับอนุญาตเพียงเพราะ client ถูกกำหนดให้ต้องเพิกเฉยต่อ
key ใน response ที่ไม่รู้จัก shape ของ request เป็นแบบปิด — key ที่ไม่รู้จักจะถูกปฏิเสธ ไม่ใช่ถูกเพิกเฉย
การยืนยันตัวตน
หัวข้อที่มีชื่อว่า “การยืนยันตัวตน”ทุก route ของปลั๊กอินรับ Authorization: Bearer <token> โดย token คือ dwp_ ตามด้วยอักขระ
URL-safe 43 ตัวจากความสุ่ม 256 บิต core เก็บเพียง hash SHA-256 ของมันและไม่สามารถแสดงมันได้อีก
ปลั๊กอินได้รับมันเพียงครั้งเดียวตอน activation
route เหล่านี้อยู่ใต้ /api/plugin/v1 พวกมันไม่ต้องการ header Origin และไม่ต้องการ cookie
เพราะ server ไม่ได้ส่งทั้งสองอย่าง core resolve installation และไซต์ ก่อน ที่จะอ่าน body ของ request ใด ๆ ตามลำดับนี้: ปฏิเสธไซต์หรือ
ฐานข้อมูลที่ผู้เรียกระบุชื่อมา, resolve token ไปยัง installation ที่ active หนึ่งตัว, ใช้ rate limit,
resolve ไซต์, route ไปยังฐานข้อมูลของ tenant
ผลที่ควรระบุให้ชัด:
- ไซต์ได้มาจาก token ปลั๊กอินระบุไซต์เองไม่ได้ และการส่ง
X-Site-Idมาเลยคือinvalid_request - cookie ของผู้ใช้ไม่ใช่การยืนยันตัวตนของปลั๊กอิน และ token ของปลั๊กอินจะไม่ถูกยอมรับบน route ด้านการดูแลระบบใดเลย
- installation ที่เป็น
pending,disabledและrevokedจะตอบplugin_unauthorizedก่อนที่จะมี การเข้าถึง tenant ใด ๆ ทุก installation บนไซต์ที่ไม่ active ก็เช่นกัน
| Header | ที่ไหน | ความหมาย |
|---|---|---|
Authorization: Bearer <token> |
ทุก request ของปลั๊กอิน | token ของ installation บังคับ |
Idempotency-Key |
transition, การเขียน, draft, media และข้อเสนอ; การเตรียมเวอร์ชันอนาคตใช้การติดตั้ง รีลีส และรายการเดิมแทนคีย์ | บังคับ อักขระ 1 ถึง 128 ตัวในช่วง \x21–\x7e (ASCII ที่พิมพ์ได้ ไม่มีช่องว่าง) เก็บไว้ 30 วัน /launch/exchange ไม่ใช้ |
Content-Type: application/json |
request ที่มี body | รูปแบบ body เดียวที่รองรับ |
X-Site-Id |
ไม่เคย | ถูกปฏิเสธ ไซต์มาจาก token |
Retry-After |
บนคำตอบที่ลองใหม่ได้ | core ส่งค่าเป็นวินาทีเมื่อสถานะเป็น 429 ไคลเอนต์รับวันที่ HTTP ในคำตอบขาเข้าที่ลองใหม่ได้ด้วย ให้รอตามค่าที่ระบุภายในขีดจำกัดจำนวนครั้ง อายุ และระยะเวลารอ |
Referrer-Policy: no-referrer |
response ของ launch จาก core และหน้าจัดการของคุณ | core ตั้งค่านี้เฉพาะบน response ของ launch ของตัวเองเท่านั้น จากนั้นเบราว์เซอร์จะเปิด management_url ของคุณพร้อม dee_wan_launch ใน query ดังนั้นหน้าของคุณต้องส่ง Referrer-Policy: no-referrer เอง และลบรหัสออกจาก address bar: แลกรหัสฝั่ง server แล้ว redirect ไปยัง URL เดิมโดยไม่มี dee_wan_launch |
ขีดจำกัด
หัวข้อที่มีชื่อว่า “ขีดจำกัด”| ขีดจำกัด | ค่า |
|---|---|
| Request body | 16384 ไบต์ เกินขีดจำกัดคือ limit_exceeded |
| Body ของการเขียนฟิลด์หรือข้อเสนอ | 81920 ไบต์, 50 ฟิลด์, ค่ารวม 65536 ไบต์ |
| Body ของ draft | 1916384 ไบต์ draft หนึ่ง 1900000 ไบต์ 200 รายการต่อบุคคล |
| Body ของ media | 33619968 ไบต์ ไฟล์หนึ่ง 33554432 ไบต์ |
| Manifest body | 32768 ไบต์ |
| Idempotency key | 128 อักขระ |
| หน้าของเนื้อหา | 50 รายการ, ค่าเริ่มต้น 20 |
| รายการของ delegation | id ของรายการ 100 ตัวต่อการอ่านหนึ่งครั้ง |
| Request ต่อ installation | 120 ต่อหน้าต่าง 60s, ใช้ installation เป็น key |
| อายุของ launch code | 60s, ใช้ครั้งเดียว, เก็บแบบ hash |
| ช่วงซ้อนทับตอน rotate token | ไม่เกิน 10 นาที และสิ้นสุดเมื่อมี request แรกที่ใช้ token ใหม่ |
| Idempotency record | 30 วัน หลังจากนั้น key เดิมคือคำสั่งใหม่ |
| อายุของ delegation | ไม่มีขีดจำกัดเวลา ดู Delegation |
| การเรียกใช้ | 10 วินาทีสำหรับ POST การแลกรหัส และคำตอบรวมกัน รหัสหมดอายุพร้อมกัน |
| คำตอบของการเรียกใช้ | 65536 ไบต์ |
| ข้อมูลเข้าของการเรียกใช้ | 32768 ไบต์ของค่าการดำเนินการหรือข้อเท็จจริงของนโยบาย |
| การเล่นซ้ำของการดำเนินการ | 24 ชั่วโมงสำหรับ Idempotency-Key หนึ่งตัวของผู้เรียกหนึ่งคน |
Capability
หัวข้อที่มีชื่อว่า “Capability”| Capability | สิ่งที่อนุญาต |
|---|---|
content:read |
route สำหรับอ่านเนื้อหา ภายในโมเดลที่ได้รับ grant |
workflow:read |
บล็อก workflow ในการอ่าน: state, revision และ transition ที่ข้ามขอบเขตการเผยแพร่ คำสั่งต้อง pin workflow.revision ดังนั้นปลั๊กอินที่ส่งคำสั่งต้องมีสิ่งนี้ |
workflow:publish |
คำสั่ง kind: publish |
workflow:unpublish |
คำสั่ง kind: unpublish |
workflow:locale |
คำสั่งที่ระบุ locale หนึ่งภาษาและเคลื่อนย้ายเฉพาะภาษานั้น และรายการ workflow.locales ตอนอ่าน หากไม่มี คำสั่งที่ระบุ locale จะได้ capability_refused คำสั่งที่ไม่มี locale จะเคลื่อนย้ายทั้ง translation group เสมอ |
workflow:release |
เตรียมและอ่านเวอร์ชันอนาคตของการติดตั้งนี้ หรือส่งคำสั่งเผยแพร่และเลิกเผยแพร่ที่มีขีดจำกัด โดย commit แบบอะตอมมิกครั้งเดียวในฐานข้อมูลเว็บไซต์ |
content:write |
บันทึกฟิลด์ค่าของ item ในนามบุคคลที่มอบสิทธิ์ โดย pin กับเวอร์ชันปัจจุบันของ item |
content:create |
สร้างรายการภายในสิทธิ์ปัจจุบันของบุคคลนั้น |
content:delete |
ย้ายรายการไปถังขยะภายในสิทธิ์ปัจจุบันของบุคคลนั้น |
draft:write |
อ่าน เขียน และทิ้ง working draft ของบุคคลที่มอบสิทธิ์เอง |
media:write |
อัปโหลด media ในนามบุคคลที่มอบสิทธิ์ ซึ่งต้องมี media:upload |
media:read |
อ่านไฟล์และ metadata ของสื่อที่มีอยู่ |
media:update |
แก้ metadata ของสื่อที่มีอยู่ |
media:delete |
ลบสื่อที่ไม่ใช้งานด้วยสิทธิ์ media:delete ปัจจุบัน และตรวจการอ้างอิงในประวัติที่เก็บไว้ |
content:restore |
กู้รายการจากถังขยะด้วยสิทธิ์ลบและสิทธิ์ภาษาปัจจุบันของผู้ใช้ |
comments:read |
อ่านความคิดเห็นผู้เข้าชมด้วยสิทธิ์ตรวจทานปัจจุบันและการมองเห็นโมเดลที่ได้รับสิทธิ์ |
comments:moderate |
จัดการความคิดเห็นผ่านการตรวจความยินยอมและความขัดแย้งของสถานะที่มีอยู่ |
redirects:read |
อ่าน redirect ด้วยสิทธิ์ site:settings ปัจจุบัน |
redirects:write |
ตรวจและแก้ redirect ผ่านการตรวจรีวิชัน เมนูและ SEO และรูปแบบ redirect เดิม |
mail:send |
ส่งเทมเพลตและผู้รับที่ผู้ดูแลอนุมัติ ด้วยสิทธิ์ site:plugins ปัจจุบันและค่าทดแทนที่ประกาศและจำกัดไว้ |
renderer:metadata |
บันทึกเมทาดาทาที่ประกาศสำหรับแต่ละภาษาเป็นเวอร์ชันฉบับร่างใหม่ โดยค่า SEO และการยืนยันเว็บไซต์จากระบบหลักมีลำดับความสำคัญสูงกว่า |
content:propose |
เสนอค่าฟิลด์ให้ editor ตรวจ และอ่านข้อเสนอของ installation นี้ |
media:source |
ตอบ media_sources ของ manifest: ผู้ใช้เรียกดูภายในตัวเลือกสื่อและคัดลอกไฟล์ที่เลือกเข้าคลังของไซต์เอง หรือลิงก์ไฟล์สำหรับ source ที่ประกาศโหมด reference ไม่อ่านอะไรจาก core |
grant (สิทธิ์ที่มอบให้) คือส่วนตัดกันของ capability เหล่านี้กับ list ของ id ของโมเดลเนื้อหาต่อไซต์ list โมเดลที่ว่างหมายถึงไม่มีสิทธิ์เข้าถึงเนื้อหา — ไม่ใช่ทุกโมเดล capability ที่อยู่นอกคำขอใน manifest ที่เก็บไว้ ไม่สามารถ grant ได้ ดังนั้นการอัปเดตปลั๊กอินไม่มีทางขยาย grant ที่มีอยู่ได้
สถานะของ installation
หัวข้อที่มีชื่อว่า “สถานะของ installation”pending, active, disabled, revoked มีเพียง active ที่เรียก plugin API ได้ revoked เป็นสถานะสุดท้าย:
token ของมันจะไม่กลับมาใช้ได้อีก และการถอนการติดตั้งจะ revoke ก่อนสิ่งอื่นใด
การส่งมอบตอน activation
หัวข้อที่มีชื่อว่า “การส่งมอบตอน activation”ตอนติดตั้ง (kind: "activate") และตอน rotate token (kind: "rotate") core จะ POST
$defs/activation_handoff เป็น JSON ไปยัง activation_url ของ manifest ซึ่งมี token ดิบ
และ activation_code ที่ผู้ดูแลวางลงใน Dee Wan ปลั๊กอินเป็นผู้ออกรหัสนั้น หนึ่งรหัสต่อการติดตั้งหรือ
การ rotate หนึ่งครั้ง และต้องตรวจมัน core ยอมรับเฉพาะรหัสที่ตรงกับ ^[A-Za-z0-9_-]{16,128}$
2xx ใดก็ตามคือการยอมรับ token status อื่นใด, redirect หรือการไม่ตอบภายใน 5s คือการปฏิเสธ
token ยังใช้ไม่ได้ขณะที่ core รอคำตอบนั้น: installation ยังคงเป็น pending จนกว่า
core จะได้รับ 2xx ของคุณ การเรียก /api/plugin/v1 จากภายใน handler จะได้คำตอบ
plugin_unauthorized ให้เก็บ token ตอบ 2xx แล้วจึงเรียก /context การ rotate ทำงาน
แบบเดียวกัน: token ใหม่ใช้ได้หลังจาก 2xx ของคุณเท่านั้น
Delegation
หัวข้อที่มีชื่อว่า “Delegation”บุคคลหนึ่งเปิดปลั๊กอินจาก Dee Wan ปลั๊กอินแลก launch code ที่
/launch/exchange และได้รับ delegation_id การแลกรหัสของการดำเนินการกับรายการก็คืนค่านี้เช่นกัน
โดยผูกกับรายการนั้น ทุกคำสั่งต้องระบุหนึ่งตัว และการอ่านอาจระบุ
หนึ่งตัว มันบอกว่าใครเป็นผู้ร้องขอ มันไม่เพิ่ม capability ใดเกินกว่า grant ของ installation
- ไม่มีขีดจำกัดเวลา delegation ไม่หมดอายุตามเวลา ดังนั้นรายการตั้งเวลาจึงใช้มันได้ในอีกหลายวันหรือ หลายสัปดาห์ต่อมา
- มันหยุดใช้งานได้ เมื่อบุคคลของมันถูกปิดใช้งานหรือไม่ได้เป็นสมาชิกของไซต์อีกต่อไป
(
requester_unauthorized) และหยุดถาวรเมื่อ installation ถูกถอนการติดตั้ง ซึ่งจะ revoke token ของมัน (plugin_unauthorizedในทุก request) ขณะที่ installation ถูกปิดใช้งานหรือไซต์ ไม่ active ทุก request ก็จะตอบplugin_unauthorizedเช่นกัน - อำนาจถูกอ่านซ้ำในทุก request คำสั่งจะถูกปฏิเสธด้วย
requester_unauthorizedเมื่อ บุคคลนั้นไม่สามารถทำ transition นั้นได้อีกต่อไป การอ่านจะตอบtransitions: []แทน - Delegation แบบ content-action (มีการตั้ง
instance_id) พูดแทนได้เฉพาะ translation group ของ รายการที่ถูก launch เท่านั้น: รายการนั้น คำแปลของมัน และรายการหลักของกลุ่ม รายการอื่นใด หรือรายการที่ถูก launch แต่ไม่มีอยู่แล้ว คือrequester_unauthorized - Delegation แบบ
manage(instance_idเป็น null) พูดแทนรายการของโมเดลในmodel_idsของมัน: โมเดลใน grant ที่บุคคลนั้นอ่านได้ตอน launch ทุกรายการหรือเฉพาะรายการของตัวเอง - โมเดลถูกตรวจซ้ำในทุก request รายการที่โมเดลไม่อยู่ใน
model_idsหรือที่บุคคลนั้นอ่านไม่ได้แล้ว คือrequester_unauthorized/delegations/:delegationIdแสดงสิ่งที่ delegation เข้าถึงได้ในตอนนี้ - รายการของตัวเองถูกตรวจทีละรายการ ภายใต้
read:ownหรือupdate:ownโมเดลจะกลับมาเป็นentries: "checked"/delegations/:delegationId/entriesบอกว่าในรายการที่คุณถืออยู่ บุคคลนั้นอ่านรายการใดได้ในตอนนี้ และทำอะไรกับรายการนั้นได้บ้าง อย่าแสดงสิ่งที่คำตอบตัดออก - credential จำกัดมัน delegation ที่เปิดโดย credential ของ management มีเฉพาะ capability ของ
installation ที่ scopes ของ credential นั้นอนุญาต คำสั่งที่อยู่นอกนั้นคือ
capability_refused - grant ของโมเดลถูกตรวจซ้ำในทุก request รายการที่อยู่นอก grant ปัจจุบันคือ
content_not_foundไม่ว่า delegation จะเป็นแบบใด - ค่า
actionสาธารณะถูกส่งกลับตามที่เปิดไว้ คำขอที่ได้รับมอบสิทธิ์ครั้งต่อไปจะตรวจการทำงานที่ต้องใช้ตามคำประกาศและสิทธิ์ปัจจุบันของผู้ใช้ การเปิดไว้ก่อนหน้าไม่ทำให้ใช้สิทธิ์ที่ถูกเพิกถอนแล้วได้
การกำหนดสิทธิ์การทำงานของปลั๊กอินผ่านบทบาท
หัวข้อที่มีชื่อว่า “การกำหนดสิทธิ์การทำงานของปลั๊กอินผ่านบทบาท”ประกาศการทำงานแยกกันด้วย role_actions: [{ id, label }] โดย id ใช้รูปแบบตัวระบุภายในที่คงที่เช่นเดียวกับ operation ผู้ดูแลกำหนดสิทธิ์ที่ การตั้งค่า → บทบาท และบทบาทเก็บสิทธิ์เป็น plugin_actions: ["<manifest-id>/<action-id>"] บทบาทที่เข้าถึงเนื้อหาเหมือนกันจึงมีสิทธิ์ใช้การทำงานของปลั๊กอินต่างกันได้
ระบุ requires_actions: ["<action-id>"] ในการทำงานกับรายการ มุมมองผู้ดูแล หรือ operation สำหรับมุมมองจัดการที่มีชื่อ ให้ใช้ manage_view_action_requirements: { "<view-id>": ["<action-id>"] } การทำงานและมุมมองทั้งหมดต้องประกาศใน manifest เดียวกัน ตัวระบุที่ซ้ำ ไม่รู้จัก หรือเป็นของปลั๊กอินอื่นจะถูกปฏิเสธ ข้อกำหนดนี้ไม่เปลี่ยนความสามารถที่อนุญาตตอนติดตั้ง สิทธิ์เข้าถึงโมเดล ข้อจำกัดฟิลด์และภาษา หรือสิทธิ์ในขั้นตอนงาน
ระบบตรวจสิทธิ์เมื่อแสดง เปิด และเรียกใช้การทำงาน รวมถึงคำขอที่ได้รับมอบสิทธิ์ เมื่อลบสิทธิ์หรือคำประกาศการทำงาน เซสชันเดิมจะใช้การทำงานนั้นไม่ได้ ผู้ดูแลระดับสูงหรือผู้ดูแลที่มีสิทธิ์ระบบ * กำหนดสิทธิ์ครั้งแรกได้ แต่ site:plugins เพียงอย่างเดียวไม่ให้สิทธิ์ใช้การทำงาน การกำหนดสิทธิ์เดิมของปลั๊กอินที่ถอนการติดตั้งแล้วคงไว้ได้โดยไม่ต้องแก้ไข แต่ไม่มีผลขณะที่ไม่มีคำประกาศรองรับ
ข้อมูลรับรองของ Management API ต้องมี scope plugin_action:<manifest-id>/<action-id> ที่เลือกไว้อย่างชัดเจนด้วย plugins:use เพียงอย่างเดียวไม่เพียงพอ ตอนออกข้อมูลรับรอง ระบบตรวจคำประกาศของปลั๊กอินที่ติดตั้งและสิทธิ์ของผู้สร้าง ตอนใช้งาน ระบบใช้เฉพาะสิทธิ์ที่ทั้ง scope และสิทธิ์ปัจจุบันของผู้สร้างอนุญาต สิทธิ์ระบบ * ของผู้สร้างไม่ขยายข้อมูลรับรองเกินการทำงานที่เลือกไว้
การดำเนินการและนโยบาย
หัวข้อที่มีชื่อว่า “การดำเนินการและนโยบาย”manifest ประกาศ operations (ไม่เกิน 8) และ policies (ไม่เกิน 8) ได้ core เรียกใช้สิ่งเหล่านี้บน
ปลั๊กอิน core วาดทุกฟอร์มและทุกผลลัพธ์ด้วยคอมโพเนนต์ของตัวเอง ไม่มีสิ่งใดที่ปลั๊กอินส่งมาเป็น markup
หรือโค้ด
- การดำเนินการ มี
inputแบบปิดไม่เกิน 8 ช่อง —text(มีmax_length),number(min,max,integer),boolean,select(optionsแบบปิด) — และรายการresultของคอมโพเนนต์ CMS:text,rows(คีย์/ค่า),links(https เท่านั้น) และjson(ให้ดาวน์โหลด)scope: "site"เรียกใช้จาก การตั้งค่า → ปลั๊กอิน และต้องมีsite:pluginsscope: "entry"เรียกใช้กับรายการเดียวของ โมเดลที่ให้สิทธิ์ซึ่งผู้ใช้อ่านได้ ถ้ามีdestructive: trueผู้ใช้ต้องแก้ไขรายการนั้นได้ด้วยและยืนยันก่อน ต้องระบุaudienceการดำเนินการinteractiveแสดงและเรียกใช้ได้ในหน้าผู้ดูแล, API การจัดการ, CLI และ MCP การดำเนินการautomationไม่แสดงในที่เหล่านั้น และเส้นทางเรียกใช้เหล่านั้นปฏิเสธมัน มีเพียง กระบวนการของ core ที่ระบุชื่อ (การส่งต่อจากตัววางแผนเนื้อหาไปยัง Scheduling) ที่เรียกใช้ได้ ผ่าน transport เดียวกัน อำนาจปัจจุบัน สิทธิ์ idempotency และการบันทึกตรวจสอบเดียวกัน - นโยบาย ประกาศ
kindหนึ่งชนิด:save(การบันทึกเนื้อหาทุกครั้ง รวมถึงการบันทึกที่เปลี่ยนเฉพาะลิงก์ สื่อ หรือการตั้งค่าการค้นหา)restore(การกู้คืนเวอร์ชันเก่า หรือรายการที่ออกจากถังขยะ)delete(รายการ หรือภาษาที่ถูกย้ายลงถังขยะ หรือถูกลบถาวร)publish,unpublishและtransition(การย้ายเวิร์กโฟลว์ทุกครั้ง รวมถึงการย้ายตามเวลาและจากปลั๊กอิน) ข้อมูลเข้าที่ผูกไว้คือ$defs/policy_facts: ชนิด id และ slug ของโมเดล id ของรายการ (null สำหรับรายการใหม่) ภาษาchanged_fields,valuesและในกรณีที่ใช้ได้links,media,seo,actionและtransitionสำหรับsaveและrestoreจะมีส่วนที่เปลี่ยนของตัวที่จะบันทึก สำหรับชนิดอื่น คือทั้งเวอร์ชันที่เกี่ยวข้อง ลิงก์ที่ทุกภาษาใช้ร่วมกันและสื่อมากับภาษาหลักเท่านั้น ไม่มีข้อมูลรับรองและไม่มี เนื้อหาอื่น นโยบายตอบ$defs/policy_reply:allow,warningพร้อมข้อความ,refuseพร้อมรหัสและข้อความ หรือ — เฉพาะsaveและrestore—transformพร้อมvalues,links,mediaหรือseoที่ใช้แทนfieldsระบุคีย์ของช่อง - การดำเนินการอาจเป็นคอลัมน์ในรายการเนื้อหาหรือการทำงานกับแถวก็ได้ คอลัมน์คือ
scope: "page"กับaudience: "column"ชนิดcell(text,badgeหรือlink)result: ["cells"]ไม่มีinputและไม่ใช่destructiveสำหรับโมเดลหนึ่งในสิทธิ์ มันได้รับ$defs/column_requestได้แก่โมเดลและรหัสของแถวไม่เกิน 50 แถวที่ คนนั้นอ่านได้ ไม่ใช่ค่า และตอบด้วยบล็อกcellsหนึ่งบล็อก มีไม่เกินหนึ่งเซลล์ต่อแถวที่ถูกระบุ แต่ละเซลล์{ id, text, tone?, url? }(toneสำหรับป้ายสีurlแบบ https สำหรับลิงก์ ข้อความไม่เกิน 80) มันอ่านสิ่งที่ต้องใช้ ผ่านสิทธิ์ของตัวเอง คอลัมน์ไม่สร้างการมอบสิทธิ์ และไม่ถูกแสดงรายการหรือรันเป็นการดำเนินการทั่วไป การทำงานกับแถวคือการ ดำเนินการentryแบบ interactive ที่มีlist_action: truecore รันมันหนึ่งครั้งต่อแต่ละแถวจากไม่เกิน 25 แถวที่คนเลือก โดยตรวจสิทธิ์ปัจจุบันของคนนั้นต่อแถว requiresแสดง capability ของการติดตั้งจากrequested_capabilitiesระหว่างที่สิทธิ์ยังขาดอย่างใด อย่างหนึ่ง รายการนั้นใช้ไม่ได้ การรับ manifest ใหม่ไม่เคยขยายสิทธิ์ รายการใหม่ที่ต้องการมากกว่าจึงใช้ ไม่ได้จนกว่าผู้ดูแลจะให้สิทธิ์
การเรียกใช้หนึ่งครั้งตามลำดับ:
- core บันทึกการเรียกใช้ — การติดตั้ง ไซต์ ผู้เรียก id ที่ประกาศ โมเดลและรายการ (ถ้ามี) digest ของ
ข้อมูลเข้า เวลาหมดอายุ — และ SHA-256 ของรหัส
dwi_แบบใช้ครั้งเดียว - core POST
$defs/invocation_envelopeไปยังendpointที่ประกาศ: เวอร์ชันโปรโตคอล id การติดตั้ง id การเรียกใช้ รหัส และเวลาหมดอายุ ไม่มีเนื้อหาและไม่มีข้อมูลรับรอง การ redirect ถูกปฏิเสธ - ปลั๊กอินส่งรหัสไปที่
POST /api/plugin/v1/invocations/exchangeพร้อม bearer token ของตัวเอง แล้ว ได้ข้อมูลเข้าที่ผูกไว้ ($defs/invocation_binding) core ใช้รหัสได้ครั้งเดียว - ปลั๊กอินตอบ POST ของ core ด้วย HTTP 200 และ
$defs/operation_replyหรือ$defs/policy_reply
core รับคำตอบเฉพาะเมื่อการติดตั้งนี้แลกรหัสของการเรียกใช้นี้และยังครอบคลุมอยู่: ใช้งานอยู่ เวอร์ชันและ การประกาศเดิม capability ที่ต้องใช้และโมเดลยังได้รับสิทธิ์ครบ นอกนั้น core จัดประเภทและเก็บเพียง digest ไม่ใช่เนื้อความ ไว้ในบันทึกการตรวจสอบ:
| ความล้มเหลว | เมื่อ |
|---|---|
plugin_timeout |
ไม่มีคำตอบครบภายใน 10 วินาที |
plugin_unreachable |
เชื่อมต่อไม่ได้ redirect หรือ 5xx |
plugin_response_invalid |
สถานะอื่น ไม่ตรงสคีมาคำตอบ ใช้คอมโพเนนต์ผลลัพธ์ที่ไม่ได้ประกาศ ใหญ่เกินไป หรือตอบโดยไม่แลกรหัส |
plugin_refused |
การดำเนินการตอบ status: "refused" พร้อมรหัสและข้อความของตัวเอง |
plugin_unavailable |
การติดตั้งถูกปิด ถอน ลดสิทธิ์ หรือเปลี่ยนระหว่างการเรียกใช้ |
มีเท่านี้: plugin_timeout, plugin_unreachable, plugin_response_invalid, plugin_refused, plugin_unavailable อย่าตอบก่อนแลกรหัส
และอย่าแคชข้อมูลที่ผูกไว้ การเรียกใช้แต่ละครั้งมีรหัสของตัวเอง
ระบบหลักใช้คำตอบของนโยบายอย่างไร
หัวข้อที่มีชื่อว่า “ระบบหลักใช้คำตอบของนโยบายอย่างไร”- ระบบหลักถามหลังการตรวจของตัวเอง (ฟิลด์ กฎ สิทธิ์ เวิร์กโฟลว์ การเผยแพร่) และก่อนบันทึก นโยบายไม่แทนที่การตรวจเหล่านั้น และไม่ย้ายเวิร์กโฟลว์เลย
- ระบบถามการติดตั้งที่ใช้งานอยู่ซึ่งสิทธิ์ครอบคลุมโมเดลของรายการและนโยบายพร้อมใช้งาน ถามพร้อมกัน
ไม่เกิน 8 รายการในเวลาเดียวกัน การบันทึกหรือการกู้คืนถามหนึ่งครั้งต่อภาษาที่ค่า ลิงก์ สื่อ หรือการตั้งค่าการค้นหาเปลี่ยน
การเผยแพร่ การยกเลิกการเผยแพร่ การลบ หรือการย้าย ถามหนึ่งครั้งต่อภาษาที่ได้รับผลกระทบ การกู้คืนถามนโยบาย
saveและrestore transformแทนที่ส่วนของรายการและภาษาที่ถูกถามตามคีย์ฟิลด์ และไม่มีอย่างอื่น: ไม่ได้ระบุรายการ จึงเข้าถึง รายการอื่นไม่ได้valuesและlinksต่อภาษาลงในภาษานั้น ลิงก์ที่ทุกภาษาใช้ร่วมกันและmediaรับจากภาษาหลัก เท่านั้นseoแทนที่การตั้งค่าการค้นหาของภาษานั้น (รูปแบบเดียวกับตัวแก้ไข ภาพเป็น{ media_id, alt }) รายการ แทนที่ทั้งรายการ การกู้คืนรับเฉพาะvaluesและseoจากนั้นระบบหลักรันการเขียนทั้งหมดอีกครั้งโดยใส่ส่วนของคุณ ผ่านทุกกฎที่ข้อมูลจากผู้ใช้ต้องผ่าน (กฎฟิลด์ rich text ความสัมพันธ์ สื่อ ความไม่ซ้ำ สิทธิ์) ส่วนที่ระบบปฏิเสธจะทำให้ การเขียนถูกปฏิเสธเป็นplugin_policy_transform_invalidพร้อมสาเหตุ สองนโยบายที่เปลี่ยนส่วนเดียวกันต่างกันจะถูก ปฏิเสธเป็นplugin_policy_transform_conflictนโยบายของคุณไม่ถูกถามอีกในรอบที่สอง ผลลัพธ์แสดงoutcome: "transformed"พร้อมฟิลด์ที่คุณเปลี่ยนและmessageที่ไม่บังคับ และเวอร์ชันที่เก็บบันทึกไว้ในmeta.policy_transformstransform ที่ไม่เปลี่ยนอะไรคือการอนุญาตtransformสำหรับชนิดอื่นเป็นคำตอบที่ระบบหลักไม่รับrefuseปฏิเสธการเขียนเสมอ ตัวแก้ไขจะระบุชื่อปลั๊กอินและนโยบายของคุณ และแสดงข้อความของคุณที่ฟิลด์ที่คุณระบุwarningให้การเขียนผ่านและแสดงข้อความ ไม่มีใครต้องส่งซ้ำ- หากหมดเวลา ระบบล่ม หรือคำตอบที่ระบบหลักไม่รับ จะเป็นไปตามโหมดที่ผู้ดูแลเลือกให้นโยบายใน
การตั้งค่า → ปลั๊กอิน:
warn(ค่าเริ่มต้น) ให้การเขียนผ่านพร้อมคำเตือนrequiredปฏิเสธการเขียน caller.viaคือperson,management_credential,plannerเมื่อตัววางแผนเนื้อหาทำงานแทนเจ้าของแผน หรือpluginเมื่อกำลังตรวจการเขียนที่ปลั๊กอินอื่นทำแทนบุคคล การนำเข้า สเปรดชีต และการกู้คืน ถามในนามของบุคคลที่สั่งงาน- การเขียนจะบันทึกก็ต่อเมื่อสิ่งที่คุณเห็นยังเป็นปัจจุบัน การเปลี่ยนแปลงระหว่างนั้นคือข้อขัดแย้งของเวอร์ชันตามปกติ และคำตอบของคุณจะไม่ถูกใช้กับเนื้อหาอื่น
Hook ก่อนการดำเนินการ
หัวข้อที่มีชื่อว่า “Hook ก่อนการดำเนินการ”manifest ประกาศ hooks ได้ไม่เกินหนึ่งรายการต่อชนิด คือ upload_metadata และ comment_moderation แต่ละรายการมี id, label, endpoint HTTPS ใน origin เดียวกัน และ requires (capability ที่อยู่ใน requested_capabilities) hook ปิดอยู่จนกว่าผู้ดูแลจะเปิดให้ installation ใน การตั้งค่า → ปลั๊กอิน Core ถาม hook ที่เปิดอยู่ ก่อน การดำเนินการ ไม่ใช่หลังจากนั้น: upload_metadata ก่อนเก็บไฟล์ใหม่ในคลัง และ comment_moderation ก่อนเก็บความคิดเห็นของผู้เยี่ยมชม
- hook ถูกเรียกผ่านระบบขนส่ง invocation เดียวกัน โดย binding มี
kind: "hook",caller: nullและไม่มี delegation Core บอก hook ว่าถูกถามอะไร และไม่เคยบอกว่าใครถาม: ไม่มีบุคคล อีเมล credential ไบต์ของไฟล์ หรือรายการอื่น upload_metadata: ข้อมูลนำเข้าคือ$defs/hook_upload_facts(ชื่อไฟล์ ประเภท MIME ขนาด โฟลเดอร์ และข้อความแทนรูป; ความกว้างและความสูงเป็นnullเพราะยังไม่ได้วัด) ตอบด้วย$defs/hook_upload_reply:acceptจะใส่normalizedด้วยก็ได้ (filenameใหม่ที่คงนามสกุลเดิม และข้อความแทนรูปเฉพาะภาษาที่การอัปโหลดระบุไว้แล้ว) หรือrefuseพร้อมรหัสและข้อความที่ผู้อัปโหลดอ่านได้ (422upload_hook_refused)comment_moderation: ข้อมูลนำเข้าคือ$defs/hook_comment_facts(รายการเนื้อหา ID ของความคิดเห็น ความคิดเห็นแม่ ชื่อผู้เขียน เว็บไซต์ และข้อความ; ไม่มีอีเมล) ตอบด้วย$defs/hook_comment_reply:approve,hold(ยังรอการตรวจ) หรือreject(เก็บเป็นสแปม หรือเป็น refused เมื่อมีas: "refused")- hook ที่ตอบไม่ได้จะไม่อนุมัติเด็ดขาด การหมดเวลา (5 วินาที) ระบบล่ม เนื้อหาที่ไม่ใช่คำตอบที่กำหนด หรือ installation ที่ถูกปิดหรือเปลี่ยนระหว่างทำงาน จะปฏิเสธการอัปโหลด (503
upload_hook_unavailableไม่บันทึกอะไร) หรือปล่อยความคิดเห็นให้รอการตรวจ - retry identity คือ digest ของคำถาม: การอัปโหลดซ้ำหรือความคิดเห็นที่ส่งซ้ำจะได้คำตอบแรกที่ ยอมรับแล้ว กลับมานาน 24 ชั่วโมงแทนการถามใหม่ คำถามที่ล้มเหลวจะไม่ถูกเล่นซ้ำ คำถามเดิมครั้งถัดไปจะถามใหม่
Media source
หัวข้อที่มีชื่อว่า “Media source”manifest อาจประกาศ media_sources (สูงสุด 4) และขอ media:source แต่ละ source คือคลังที่ผู้ใช้เรียกดูได้ภายใน
ตัวเลือกสื่อ ข้างคลังของไซต์เอง และผ่าน management API แต่ละ
source ประกาศ modes: copy (core คัดลอกไฟล์ที่เลือกเข้าไซต์ เนื้อหาที่เผยแพร่จึงไม่ขึ้นกับ source), reference
(core เก็บเฉพาะ URL การส่งมอบและตัวตนของไฟล์ และ source เก็บไบต์) หรือทั้งสอง ผู้ใช้หรือผู้เรียก API ระบุโหมดทุกครั้งที่เพิ่ม
core ไม่เดาจาก URL หรือชื่อ
- source ถูกเรียกผ่าน transport การเรียกใช้เดียวกัน โดยมี
kind: "media_source"ในข้อมูลที่ผูก และไม่มี delegation ข้อมูลเข้าที่ผูกไว้คือ$defs/media_source_request:browseพร้อมquery(ว่างสำหรับหน้าแรก)cursor(next_cursorก่อนหน้า หรือ null) และlimit(สูงสุด 24) หรือitemพร้อมitem_idที่ผู้ใช้เลือก - ตอบ
browseด้วย$defs/media_source_page_replyและitemด้วย$defs/media_source_item_replyหรือstatus: "refused"พร้อมรหัสและข้อความ แต่ละ item มีชื่อเรื่อง ชื่อไฟล์ ชนิด MIME ขนาดและมิติ (ไม่บังคับ)thumbnail_url,download_url(จำเป็นสำหรับcopy),delivery_url(จำเป็นสำหรับreference) และattribution:source_name,licenseและauthor,author_url,license_urlและsource_urlที่ไม่บังคับdescriptionของรูปภาพ (สูงสุด 125 ตัวอักษร) จะกลายเป็น alt text ในภาษาเริ่มต้นของไซต์ thumbnail_urlและdownload_urlต้องอยู่บน origin เดียวของ manifest ส่วนdelivery_urlต้องอยู่บนหนึ่งในdelivery_originsของ source (สูงสุด 4 origin เปล่า จำเป็นเมื่อมีreferenceและต้องไม่มีเมื่อไม่มี origin ของ manifest อยู่ในนั้นได้) คำตอบที่ระบุ origin อื่นคือplugin_response_invalidตัวเลือกโหลด thumbnail จาก origin ของคุณโดยตรง โดยไม่มี referrer และไม่มีข้อมูล รับรองของ Dee Wan ลิงก์ attribution แสดงไว้แต่ไม่ถูกดึง- เมื่อผู้ใช้เลือก item core ถาม
itemอีกครั้ง แล้ว GETdownload_urlโดยไม่มีข้อมูลรับรองและไม่มี redirect ภายใน 20 วินาทีและขีดจำกัดไฟล์สื่อ ไบต์ผ่านการตรวจเดียวกับการอัปโหลด: ชนิด รูปแบบ ขีดจำกัดขนาดของไซต์ และการตรวจไฟล์ซ้ำ สื่อใหม่คง attribution และ id ของปลั๊กอิน source และ item ไว้ ลงนามdownload_urlเองหากไฟล์ของคุณไม่เป็นสาธารณะ - ในโหมด
referencecore ไม่ดึงอะไร แถวสื่อเก็บdelivery_urlของคุณเป็นที่อยู่ เก็บ id ของปลั๊กอิน source และ item ของคุณเป็นตัวตน และเมทาดาทาที่คุณประกาศ item เดิมที่เพิ่มสองครั้งทำตามon_duplicateหน้าที่เผยแพร่ สำเนาไซต์ และไซต์ที่สร้าง ใช้delivery_urlตามที่เป็น จึงต้องเปิดให้บริการตราบที่ไซต์ยังใช้ core ไม่ proxy ไม่แทนที่ไบต์ และไม่เรียกคุณเมื่อ ไฟล์ถูกลบจากคลัง โหมดที่ source ไม่ได้ประกาศถูกปฏิเสธด้วยmedia_source_mode_unsupported - การเรียกดูไม่เปลี่ยนอะไร จึงไม่ถูกบันทึกตรวจสอบ สำเนาคือการอัปโหลดสื่อปกติโดยผู้ที่เลือก
- ผู้เรียกต้องมี
media:uploadการติดตั้งที่ถูกปิด สิทธิ์ที่ถูกลดจนไม่มีmedia:sourceหรือการประกาศที่เปลี่ยน ทำให้ source ใช้ไม่ได้ทันที
Route ของปลั๊กอิน
หัวข้อที่มีชื่อว่า “Route ของปลั๊กอิน”GET /api/plugin/v1/context
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/context”installation นี้คืออะไร id ของ installation, ไซต์ที่มันผูกอยู่, เวอร์ชัน protocol ที่ยอมรับ และ grant ให้อ่านตอนเริ่มต้นเพื่อรู้ว่า installation นี้ขออะไรได้บ้าง มันไม่ระบุผู้ใช้, ไม่มี hash ของ token, ไม่มีฐานข้อมูล และไม่มีโครงสร้างพื้นฐานใด
- ผู้เรียก: ปลั๊กอิน พร้อม token ของ installation
- ต้องการ: ไม่มี
- ไม่มี query ไม่มี body
- คำตอบ:
{ "data": <context> }—$defs/context
Outcome:
plugin_unauthorizedrate_limitedtemporary_failure
installation นี้ทำอะไรได้บ้าง
curl "https://cms.example/api/plugin/v1/context" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp"{ "data": { "installation_id": "plg_0000000000000000000000000000d1ee", "site": { "id": "cdocssite00000000000000001", "name": "docs-site", "default_lang": "en" }, "protocol_version": 1, "capabilities": [ "content:read", "workflow:read", "workflow:publish", "workflow:unpublish" ], "model_ids": [ "cdocsmodel0000000000000001" ] }}token ที่ไม่รู้จัก ถูก disable หรือถูก revoke
curl "https://cms.example/api/plugin/v1/context" \ -H "Authorization: Bearer dwp_UnknownTokenNotRealUnknownTokenNotRealUnkno"{ "outcome": { "code": "plugin_unauthorized", "message": "The installation token is missing, unknown, disabled or revoked.", "retry": false }}คำตอบเดียวสำหรับทั้งสี่กรณี ไม่มีสิ่งใดบอกผู้เรียกว่าเป็นกรณีใด
ปลั๊กอินระบุไซต์ไม่ได้
curl "https://cms.example/api/plugin/v1/context" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "X-Site-Id: cotherdocsite00000000001"{ "outcome": { "code": "invalid_request", "message": "A plugin request cannot name a site.", "retry": false }}ไซต์มาจาก token การส่ง header นี้มาเลยจะถูกปฏิเสธ แม้จะเป็นค่าที่ถูกต้องก็ตาม
route ของปลั๊กอินที่ไม่รู้จัก
curl "https://cms.example/api/plugin/v1/schedules" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp"{ "outcome": { "code": "content_not_found", "message": "No such plugin route.", "retry": false }}Protocol v1 มี route ข้างต้นและไม่มีอะไรอื่น 404 ตรงนี้ไม่ใช่ความล้มเหลวชั่วคราว
GET /api/plugin/v1/content
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/content”แสดงรายการเนื้อหาในโมเดลที่ได้รับ grant หนึ่งโมเดล instance หลักหนึ่งหน้าในโมเดลเดียว model_id เป็นค่าบังคับ: ไม่มีการอ่านแบบ “ทุกโมเดล” ชุด filter เป็นแบบปิด — query parameter อื่นใดคือ invalid_request ไม่ใช่ถูกเพิกเฉย — และหน้านี้เป็นสรุปแบบแคบ ไม่ใช่ snapshot ของเนื้อหา มีเพียง primary ของ translation group ที่ปรากฏ group คือหน่วยที่ transition เคลื่อนย้าย
- ผู้เรียก: ปลั๊กอิน,
content:read - ต้องการ:
content:read model_id(บังคับ) — id ของโมเดลจาก grantpublished—trueหรือfalseafter—instance_idตัวสุดท้ายของหน้าก่อนหน้าlimit— 1..50, ค่าเริ่มต้น 20- คำตอบ:
{ "data": [<summary>], "next": <instance_id|null> }—$defs/content_page
Outcome:
capability_refused— ไม่มีcontent:readหรือโมเดลอยู่นอก grantinvalid_request— ไม่มีmodel_id, filter ที่ไม่รู้จัก,limitอยู่นอกช่วงplugin_unauthorizedrate_limitedtemporary_failure
หนึ่งหน้าของหนึ่งโมเดล
curl "https://cms.example/api/plugin/v1/content?model_id=cdocsmodel0000000000000001&published=false&limit=1" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp"{ "data": [ { "instance_id": "cdocsinstance00000000000001", "primary_instance_id": "cdocsinstance00000000000001", "translation_group_id": "cdocsgroup0000000000000001", "model_id": "cdocsmodel0000000000000001", "model_slug": "article", "lang": "en", "label": "Hello", "slug": "hello", "current_version_id": "cdocsversion00000000000001", "published_version_id": null } ], "next": null}filter ที่อยู่นอก model_id, published, after, limit คือ invalid_request ไม่ใช่ถูกเพิกเฉย
ชุด filter เป็นแบบปิด
curl "https://cms.example/api/plugin/v1/content?model_id=cdocsmodel0000000000000001&sort=title" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp"{ "outcome": { "code": "invalid_request", "message": "model_id is required; filters are model_id, published, after, limit.", "retry": false }}GET /api/plugin/v1/content/:instanceId
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/content/:instanceId”อ่านรายการเดียว พร้อมการดำเนินการที่ผู้ใช้ทำได้ในตอนนี้ id, label (ชื่อเรื่องของรายการในภาษาของรายการนั้น หรือหมายเหตุของ version ปัจจุบันหากไม่มี), slug, id ของ version ปัจจุบันและ version ที่เผยแพร่ และ — เมื่อมี workflow:read — state ของ workflow, revision ของมัน และ transition ที่ข้ามขอบเขตการเผยแพร่ transition ถูกจำกัดให้แคบลงตาม capability ที่ installation นี้ถืออยู่ ส่ง delegation_id มา แล้วมันจะถูกจำกัดให้แคบลงอีกตามสิ่งที่บุคคลนั้นทำได้ ในตอนนี้ โดยอ่านซ้ำในทุก request บุคคลที่ถูกปิดใช้งานหรือไม่ได้เป็นสมาชิกของไซต์อีกต่อไปจะตอบ requester_unauthorized บุคคลที่ยังเป็นสมาชิกแต่ไม่สามารถอัปเดตรายการนี้ได้อีกต่อไปจะตอบ 200 พร้อม transitions: [] (คำสั่งจะยังคงถูกปฏิเสธด้วย requester_unauthorized) delegation แบบ content-action ถูกยอมรับเฉพาะกับรายการใน translation group ที่มันถูก launch delegation แบบ manage ถูกยอมรับกับรายการใดก็ได้ของโมเดลที่มันถูก launch ด้วย ทุก delegation ยังถูกปฏิเสธสำหรับรายการที่โมเดลไม่อยู่ใน model_ids ของมัน หรือที่บุคคลของมันอ่านไม่ได้แล้ว หากไม่มี workflow:read จะไม่มีบล็อก workflow delegation ที่ถูกต้องเพิ่ม snapshot saved ซึ่งจำกัดตามสิทธิ์ปัจจุบัน workflow.revision คือสิ่งที่ทุกคำสั่งต้อง pin ดังนั้นปลั๊กอินที่ส่งคำสั่งต้องมี workflow:read รายการที่ไม่เคยเคลื่อนผ่าน workflow ของมันเลยมี revision 0 รายการที่อยู่นอกไซต์หรือนอก grant ของโมเดลคือ content_not_found ซึ่งเป็นคำตอบเดียวกับ id ข้ามไซต์ด้วย
- ผู้เรียก: ปลั๊กอิน,
content:read - ต้องการ:
content:readและworkflow:readสำหรับบล็อกworkflow delegation_id— launch delegation ที่ถูกใช้แล้ว หรือ delegation จากข้อมูลผูกของการดำเนินการกับรายการ ไม่รับ query parameter อื่น- คำตอบ:
{ "data": <summary> }—$defs/content_summary
Outcome:
capability_refusedcontent_not_foundrequester_unauthorized— delegation ที่ระบุไม่เป็นที่รู้จัก เป็นของ installation อื่น ผูกกับ translation group อื่นหรือกับรายการที่ไม่มีอยู่แล้ว หรือบุคคลของมันถูกปิดใช้งานหรือไม่ได้เป็นสมาชิกของไซต์อีกต่อไป หรือโมเดลของรายการไม่อยู่ในmodel_idsของ delegation หรือบุคคลของมันอ่านรายการนั้นไม่ได้แล้วinvalid_requestplugin_unauthorizedrate_limitedtemporary_failure
หนึ่งรายการ พร้อม transition ที่ผู้ร้องขอทำได้ในตอนนี้
curl "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001?delegation_id=pld_0000000000000000000000000000d1ee" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp"{ "data": { "instance_id": "cdocsinstance00000000000001", "primary_instance_id": "cdocsinstance00000000000001", "translation_group_id": "cdocsgroup0000000000000001", "model_id": "cdocsmodel0000000000000001", "model_slug": "article", "lang": "en", "label": "Hello", "slug": "hello", "current_version_id": "cdocsversion00000000000001", "published_version_id": null, "workflow": { "state": "draft", "revision": 0, "transitions": [ { "to": "published", "kind": "publish" } ] } }}ให้ pin สิ่งที่คำตอบนี้ให้มา: current_version_id สำหรับการเผยแพร่, published_version_id สำหรับการยกเลิกการเผยแพร่ และ workflow.revision สำหรับทั้งสองแบบ
POST /api/plugin/v1/content/:instanceId/transitions/:targetState
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/content/:instanceId/transitions/:targetState”เผยแพร่หรือยกเลิกการเผยแพร่แบบมีเงื่อนไข ใช้เปลี่ยนสถานะการเผยแพร่เท่านั้น มันมีเงื่อนไขสี่ทางพร้อมกัน ซึ่งทั้งหมดถูกตรวจภายใน lifecycle mutation แบบ atomic เดียวกัน: version ที่ถูก pin ต้องยังเป็นตัวที่ transition จะเคลื่อนย้าย, revision ของ workflow ต้องยังเป็นตัวที่ใช้ตอนสร้างรายการตั้งเวลา, targetState ต้องเป็น transition ที่ใช้ได้จาก state ปัจจุบัน และความหมายด้านการเผยแพร่ของ transition นั้นต้องตรงกับ kind delegation ต้องครอบคลุมรายการนั้น (ดู Delegation) และอำนาจของบุคคลที่ delegate จะถูกอ่านซ้ำก่อนการเขียน draft ที่ใหม่กว่าจะไม่ถูกเผยแพร่อย่างเงียบ ๆ เลย workflow ที่เปลี่ยนไปจะไม่ถูกเดินผ่านอย่างเงียบ ๆ เลย การเผยแพร่มีผลกับทั้ง translation group ซึ่งเป็นเหตุผลที่ผลลัพธ์ระบุ instance หลัก เมื่อมี workflow:locale body ที่ระบุ locale จะเคลื่อนย้ายเฉพาะภาษานั้น: targetState ถูกตรวจกับ state ของภาษานั้นเองใน workflow.locales การยกเลิกการเผยแพร่จะ pin เวอร์ชันที่เผยแพร่ของภาษานั้นเอง และผลลัพธ์ระบุ locale ที่ถูกเคลื่อนย้าย transition ที่เผยแพร่ยังรายงาน redirect: การ redirect อัตโนมัติที่ lifecycle call เดียวกันสร้างให้ที่อยู่ที่เปลี่ยน หรือเหตุผลที่ไม่ได้สร้าง การส่งซ้ำตรงตัวได้ผลลัพธ์แรกทั้งหมด รวม locale และ redirect core เขียน redirect หลัง transition commit จนกว่าจะบันทึกผลของมัน คำสั่งและการส่งซ้ำใด ๆ จะตอบ temporary_failure พร้อมข้อความว่า transition ถูกนำไปใช้แล้ว ลองใหม่ด้วย key และ body เดิม: แล้วการส่งซ้ำจะได้ผลลัพธ์ทั้งหมด
การเผยแพร่ปกติตรึงฉบับร่างปัจจุบัน ส่วนการเผยแพร่เวอร์ชันอนาคตต้องระบุ future_draft_id คู่กับ expected_future_revision และตรึงเวอร์ชันที่บันทึกไว้ของฉบับนั้น โดยไม่เปลี่ยนฉบับร่างปกติ การเผยแพร่ซ้ำจากสถานะที่เผยแพร่แล้วทำได้เฉพาะคำสั่งเวอร์ชันอนาคตที่มีสิทธิ์ปัจจุบันเท่านั้น
- ผู้เรียก: ปลั๊กอิน,
workflow:publishหรือworkflow:unpublish - ต้องการ:
workflow:publishสำหรับkind: publish,workflow:unpublishสำหรับkind: unpublish Idempotency-Key(บังคับ) — อักขระ 1 ถึง 128 ตัวในช่วง\x21–\x7e(ASCII ที่พิมพ์ได้ ไม่มีช่องว่าง) ให้สร้างจากรายการตั้งเวลา ไม่ใช่จากนาฬิกา: replay ที่ตรงกันทุกประการจะคืนผลลัพธ์แรก และ key เดิมกับอินพุตที่ต่างกันคือidempotency_key_reusedcore เก็บ record ไว้ 30 วัน หลังจากนั้น key เดิมจะถือเป็นคำสั่งใหม่- Body —
$defs/publish_commandหรือ$defs/unpublish_commandshape เป็นแบบ ปิด: key ที่ไม่รู้จัก หรือ pin ของอีก kind หนึ่ง คือinvalid_request - คำตอบ:
{ "outcome": {...}, "data": <transition_result> }—$defs/transition_result
Outcome:
transition_applied/idempotent_replayinvalid_requestcapability_refusedrequester_unauthorized— delegation ไม่เป็นที่รู้จัก ไม่ครอบคลุมรายการนี้ หรือบุคคลของมันไม่มีอำนาจที่ transition นั้นต้องการอีกต่อไปcontent_not_foundscheduled_target_staleworkflow_conflictdependent_contentidempotency_key_reusedtransition_unavailable/transition_refusedrate_limitedtemporary_failure
เผยแพร่ draft ที่ถูก pin
curl -X POST "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001/transitions/published" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: sched:plg_0000000000000000000000000000d1ee:sch_0001:r1" \ --data '{ "kind": "publish", "expected_current_version_id": "cdocsversion00000000000001", "expected_workflow_revision": 0, "delegation_id": "pld_0000000000000000000000000000d1ee"}'{ "outcome": { "code": "transition_applied", "message": "The transition was applied.", "retry": false }, "data": { "instance_id": "cdocsinstance00000000000001", "primary_instance_id": "cdocsinstance00000000000001", "from": "draft", "to": "published", "published": true, "published_changed": true, "published_version_id": "cdocsversion00000000000001", "revision": 1, "redirect": { "status": "none", "reason": "no_public_address" }, "policy_results": [] }}คำสั่งเดิมอีกครั้ง
curl -X POST "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001/transitions/published" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: sched:plg_0000000000000000000000000000d1ee:sch_0001:r1" \ --data '{ "kind": "publish", "expected_current_version_id": "cdocsversion00000000000001", "expected_workflow_revision": 0, "delegation_id": "pld_0000000000000000000000000000d1ee"}'{ "outcome": { "code": "idempotent_replay", "message": "This command was already applied. The first result is returned.", "retry": false }, "data": { "instance_id": "cdocsinstance00000000000001", "primary_instance_id": "cdocsinstance00000000000001", "from": "draft", "to": "published", "published": true, "published_changed": true, "published_version_id": "cdocsversion00000000000001", "revision": 1, "redirect": { "status": "none", "reason": "no_public_address" }, "policy_results": [] }}การ retry หลัง network ล้มเหลวปลอดภัย: ผลลัพธ์แรกทั้งหมดจะกลับมา รวม redirect และไม่มีอะไรรันซ้ำสองครั้ง
key เดิม คำสั่งต่างกัน
curl -X POST "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001/transitions/published" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: sched:plg_0000000000000000000000000000d1ee:sch_0001:r1" \ --data '{ "kind": "publish", "expected_current_version_id": "cdocsversion00000000000001", "expected_workflow_revision": 7, "delegation_id": "pld_0000000000000000000000000000d1ee"}'{ "outcome": { "code": "idempotency_key_reused", "message": "This idempotency key was already used for a different command.", "retry": false }}ให้สร้าง key จากรายการตั้งเวลาและ revision ของมัน การตั้งเวลาใหม่คือ revision ใหม่ จึงเป็น key ใหม่
ยกเลิกการเผยแพร่ version ที่ live และถูก pin
curl -X POST "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001/transitions/draft" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: sched:plg_0000000000000000000000000000d1ee:sch_0002:r1" \ --data '{ "kind": "unpublish", "expected_published_version_id": "cdocsversion00000000000001", "expected_workflow_revision": 1, "delegation_id": "pld_0000000000000000000000000000d1ee"}'{ "outcome": { "code": "transition_applied", "message": "The transition was applied.", "retry": false }, "data": { "instance_id": "cdocsinstance00000000000001", "primary_instance_id": "cdocsinstance00000000000001", "from": "published", "to": "draft", "published": false, "published_changed": true, "published_version_id": null, "revision": 2, "policy_results": [] }}draft ที่ใหม่กว่าจะไม่ถูกเผยแพร่อย่างเงียบ ๆ เลย
curl -X POST "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001/transitions/published" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: sched:plg_0000000000000000000000000000d1ee:sch_0003:r1" \ --data '{ "kind": "publish", "expected_current_version_id": "cdocsversion00000000000001", "expected_workflow_revision": 2, "delegation_id": "pld_0000000000000000000000000000d1ee"}'{ "outcome": { "code": "scheduled_target_stale", "message": "The pinned version is no longer the one this transition would move.", "retry": false }}มีคนบันทึก draft ที่ใหม่กว่าหลังจากสร้างรายการตั้งเวลาแล้ว เป็นสถานะสุดท้าย: บุคคลเป็นผู้ตัดสินใจว่าจะทำอย่างไร
workflow ที่เปลี่ยนไปจะไม่ถูกเดินผ่านอย่างเงียบ ๆ เลย
curl -X POST "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001/transitions/published" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: sched:plg_0000000000000000000000000000d1ee:sch_0004:r1" \ --data '{ "kind": "publish", "expected_current_version_id": "cdocsversion00000000000002", "expected_workflow_revision": 0, "delegation_id": "pld_0000000000000000000000000000d1ee"}'{ "outcome": { "code": "workflow_conflict", "message": "The content moved through its workflow after this was requested.", "retry": false }}shape ของ request เป็นแบบปิด
curl -X POST "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001/transitions/published" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: sched:plg_0000000000000000000000000000d1ee:sch_0005:r1" \ --data '{ "kind": "publish", "expected_current_version_id": "cdocsversion00000000000002", "expected_workflow_revision": 2, "delegation_id": "pld_0000000000000000000000000000d1ee", "override_dependents": true}'{ "outcome": { "code": "invalid_request", "message": "The request is not valid for protocol v1.", "retry": false }}ไม่มีการ override ใน protocol v1 key ที่ไม่รู้จักจะถูกปฏิเสธ ไม่ใช่ถูกทิ้ง
mutation ที่ไม่มี idempotency key
curl -X POST "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001/transitions/published" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ --data '{ "kind": "publish", "expected_current_version_id": "cdocsversion00000000000002", "expected_workflow_revision": 2, "delegation_id": "pld_0000000000000000000000000000d1ee"}'{ "outcome": { "code": "invalid_request", "message": "Idempotency-Key is required.", "retry": false }}PUT /api/plugin/v1/content/:instanceId
หัวข้อที่มีชื่อว่า “PUT /api/plugin/v1/content/:instanceId”บันทึกค่าฟิลด์ในนามบุคคล การบันทึก lifecycle ปกติของฟิลด์ค่าที่ระบุชื่อของ item หนึ่งรายการ ทำในนามบุคคลที่มอบสิทธิ์: สิทธิ์ต่อโมเดล ความเป็นเจ้าของ และบัญชีปัจจุบันของเขาถูกอ่านใหม่ และการบันทึกเป็นของเขาในประวัติเนื้อหา การบันทึกนี้ถูก pin: expected_version_id ต้องยังเป็นเวอร์ชันปัจจุบัน มิฉะนั้นคำตอบคือ version_conflict และไม่มีอะไรถูกเขียน กฎเดียวกับที่ editor ใช้เป็นตัวตัดสินค่า — ชนิดฟิลด์ ความไม่ซ้ำ ลำดับชั้น ภาษา และขนาดเวอร์ชัน fields รับค่าของฟิลด์ได้ไม่เกิน 50 ฟิลด์ โดยค่ารวมมีขนาดไม่เกิน 65536 ไบต์ ส่งการอ้างอิงแบบมีชนิดแยกใน relations, locale_relations และ media เมื่อเปลี่ยนการอ้างอิง fields ว่างได้ ถ้าไม่มี locale ค่าจะเป็นของภาษาของ item ที่ระบุเอง ฟิลด์ slug ที่แปลได้จะเปลี่ยนที่อยู่ของภาษานั้นเท่านั้น ส่วนฟิลด์ที่ใช้ร่วมกันระบุที่อยู่ของภาษาหลัก slugs ในคำตอบคือที่อยู่ของทุกภาษา ประวัติฝั่งผู้ดูแลบันทึกบุคคลนั้นพร้อมระบุ installation นี้
- ผู้เรียก: ปลั๊กอิน,
content:write - ต้องการ:
content:write Idempotency-Key(บังคับ) — เหมือนกับ transition การส่งซ้ำได้ผลลัพธ์แรกกลับมา- Body —
$defs/content_write_commandแบบปิด - คำตอบ:
{ "outcome": {...}, "data": <save_result> }—$defs/content_save_result
Outcome:
content_saved/idempotent_replayinvalid_requestcapability_refusedrequester_unauthorized— delegation ไม่ครอบคลุม item นี้ หรือบุคคลของมันแก้ไข item นี้ไม่ได้ในตอนนี้content_not_foundversion_conflictvalidation_failed—dataระบุreasonของกฎ และfieldsเมื่อมีlimit_exceededidempotency_key_reusedrate_limitedtemporary_failure
บันทึกฟิลด์เดียว โดย pin กับเวอร์ชันปัจจุบัน
curl -X PUT "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: write:plg_0000000000000000000000000000d1ee:0001" \ --data '{ "delegation_id": "pld_0000000000000000000000000000d1ee", "expected_version_id": "cdocsversion00000000000002", "fields": { "title": "Hello from the plugin" }}'{ "outcome": { "code": "content_saved", "message": "The field values were saved as a new version.", "retry": false }, "data": { "instance_id": "cdocsinstance00000000000001", "primary_instance_id": "cdocsinstance00000000000001", "translation_group_id": "cdocsgroup0000000000000001", "version": { "id": "cdocsversion00000000000003", "version_number": 3 }, "current_version_id": "cdocsversion00000000000003", "published_version_id": null, "slugs": { "en": "hello", "fr": "hello" }, "locales": { "en": "cdocsinstance00000000000001", "fr": "cdocsinstancefr000000000001" }, "warnings": [], "policy_results": [] }}เวอร์ชันใหม่เป็นของบุคคลที่มอบสิทธิ์ pin current_version_id สำหรับการเขียนครั้งถัดไป
การเขียนที่ pin กับเวอร์ชันที่เก่ากว่า
curl -X PUT "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: write:plg_0000000000000000000000000000d1ee:0002" \ --data '{ "delegation_id": "pld_0000000000000000000000000000d1ee", "expected_version_id": "cdocsversion00000000000001", "fields": { "title": "Lost update" }}'{ "outcome": { "code": "version_conflict", "message": "The entry changed after the pinned version. Read it again before writing.", "retry": false }}ไม่มีอะไรถูกเขียน อ่าน item ใหม่แล้วตัดสินใจร่วมกับบุคคลนั้น
GET /api/plugin/v1/content/:instanceId/proposals
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/content/:instanceId/proposals”ข้อเสนอของ installation นี้สำหรับ item หนึ่งรายการ ข้อเสนอที่ installation นี้สร้างให้ item ใหม่สุดก่อน ไม่เกิน 50 รายการ ในทุกสถานะ: open, applied หรือ dismissed ข้อเสนอของ installation อื่นหรือของ management credential จะไม่แสดง
- ผู้เรียก: ปลั๊กอิน,
content:propose - ต้องการ:
content:propose - ไม่มี query ไม่มี body
- คำตอบ:
{ "data": [<proposal>] }—$defs/proposal_list
Outcome:
capability_refusedcontent_not_foundinvalid_requestplugin_unauthorizedrate_limitedtemporary_failure
POST /api/plugin/v1/content/:instanceId/proposals
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/content/:instanceId/proposals”เสนอค่าฟิลด์ให้ผู้แก้ไขรายการตรวจทาน บันทึกค่าที่เสนอสำหรับฟิลด์ที่ระบุชื่อ โดย pin กับ base_version_id เพื่อให้ผู้แก้ไขรายการตรวจทาน เนื้อหาไม่เปลี่ยน จนกว่าผู้ใช้จะนำข้อเสนอไปใช้ใน Dee Wan การกด ใช้ เป็นการบันทึกตามปกติของผู้ใช้นั้น ด้วยสิทธิ์ของตนและเทียบกับเวอร์ชันที่ pin ไว้ ตัวแก้ไขแสดงชื่อปลั๊กอินและบุคคลที่ปลั๊กอินทำแทน บุคคลที่มอบสิทธิ์ต้องยังอ่านรายการได้
- ผู้เรียก: ปลั๊กอิน,
content:propose - ต้องการ:
content:propose Idempotency-Key(บังคับ) — เหมือนกับ transition- Body —
$defs/proposal_commandแบบปิด - คำตอบ:
{ "outcome": {...}, "data": <proposal> }—$defs/proposal
Outcome:
proposal_created/idempotent_replayinvalid_requestcapability_refusedrequester_unauthorizedcontent_not_foundversion_conflict—base_version_idไม่ใช่เวอร์ชันปัจจุบันแล้วvalidation_failedlimit_exceededidempotency_key_reusedrate_limitedtemporary_failure
เสนอค่าให้ editor ตรวจ
curl -X POST "https://cms.example/api/plugin/v1/content/cdocsinstance00000000000001/proposals" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: propose:plg_0000000000000000000000000000d1ee:0001" \ --data '{ "delegation_id": "pld_0000000000000000000000000000d1ee", "base_version_id": "cdocsversion00000000000003", "fields": { "title": "A better title" }, "note": "Shorter and clearer."}'{ "outcome": { "code": "proposal_created", "message": "The proposal was created. Nothing changes until a person applies it.", "retry": false }, "data": { "id": "prop_00000000000000000000000000000d1e", "revision": 0, "instance_id": "cdocsinstance00000000000001", "lang": "en", "base_version_id": "cdocsversion00000000000003", "fields": { "title": "A better title" }, "note": "Shorter and clearer.", "source": { "kind": "plugin", "id": "plg_0000000000000000000000000000d1ee", "label": "My Plugin", }, "state": "open", "applied_version_id": null, "created_at": "2026-01-01T00:00:00.000Z", "resolved_at": null }}ไม่มีอะไรเปลี่ยน editor ของรายการแสดงข้อเสนอนี้ว่ามาจาก My Plugin ตามคำขอของบุคคลนั้น
GET /api/plugin/v1/proposals/:proposalId
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/proposals/:proposalId”ข้อเสนอหนึ่งรายการที่ installation นี้สร้าง อ่านข้อเสนอหนึ่งรายการเพื่อรู้ว่าบุคคลนำไปใช้หรือปัดทิ้ง และการนำไปใช้สร้างเวอร์ชันใด ข้อเสนอของ installation อื่น หรือของ item นอก grant คือ content_not_found
- ผู้เรียก: ปลั๊กอิน,
content:propose - ต้องการ:
content:propose - ไม่มี query ไม่มี body
- คำตอบ:
{ "data": <proposal> }—$defs/proposal
Outcome:
capability_refusedcontent_not_foundinvalid_requestplugin_unauthorizedrate_limitedtemporary_failure
GET /api/plugin/v1/drafts
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/drafts”อ่าน working draft ของบุคคล ฉบับร่างที่ยังไม่บันทึกในตัวแก้ไขของบุคคลที่มอบสิทธิ์ สำหรับรายการและภาษาหนึ่ง ซึ่งเป็นงานที่ตัวแก้ไขรายการใช้กู้คืน draft ไม่เคยเป็นเวอร์ชันและไม่เคยเป็น audit มันเป็นของบุคคลนั้น: ปลั๊กอินอ่านได้เฉพาะ draft ของบุคคลที่เปิดปลั๊กอิน target คือ id ของ item หรือ new:<model id> สำหรับ item ที่ยังไม่ถูกสร้าง ซึ่งต้องใช้ delegation แบบ manage บุคคลนั้นต้องยังแก้ไข item ได้ (หรือสร้าง item ของโมเดลนั้นได้) draft หมดอายุหลัง 30 วัน
- ผู้เรียก: ปลั๊กอิน,
draft:write - ต้องการ:
draft:write delegation_id,target,locale— บังคับทั้งหมด ไม่มีอย่างอื่น$defs/draft_query- คำตอบ:
{ "data": <draft|null>, "expired": <boolean> }—$defs/draft_read
Outcome:
capability_refusedcontent_not_foundrequester_unauthorizedinvalid_requestplugin_unauthorizedrate_limitedtemporary_failure
PUT /api/plugin/v1/drafts
หัวข้อที่มีชื่อว่า “PUT /api/plugin/v1/drafts”เขียน working draft ของบุคคล แทนที่ฉบับร่างนั้นเฉพาะเมื่อรีวิชันปัจจุบันตรงกับ expected_revision (0 เมื่อยังไม่มีฉบับร่าง) ถ้าอุปกรณ์หรือแท็บอื่นเขียนก่อนคือ draft_conflict พร้อม draft ปัจจุบันใน data.current draft หนึ่งเก็บได้ไม่เกิน 1900000 ไบต์ และบุคคลหนึ่งเก็บได้ไม่เกิน 200 รายการต่อไซต์ เกินอย่างใดอย่างหนึ่งคือ limit_exceeded data คือสถานะการทำงานของ editor Dee Wan ตรวจสอบมันเฉพาะเมื่อบุคคลบันทึก
- ผู้เรียก: ปลั๊กอิน,
draft:write - ต้องการ:
draft:write Idempotency-Key(บังคับ)- Body —
$defs/draft_write_commandแบบปิด - คำตอบ:
{ "outcome": {...}, "data": <draft> }—$defs/working_draft
Outcome:
draft_saved/idempotent_replaydraft_conflictlimit_exceededinvalid_requestcapability_refusedrequester_unauthorizedcontent_not_foundidempotency_key_reusedrate_limitedtemporary_failure
POST /api/plugin/v1/drafts/discard
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/drafts/discard”ทิ้ง working draft ของบุคคล ลบ revision ของ draft นั้นตรงตัวเท่านั้น revision ที่ใหม่กว่าจะถูกเก็บไว้และได้คำตอบ draft_conflict draft ที่ไม่มีอยู่แล้วคือ draft_discarded
- ผู้เรียก: ปลั๊กอิน,
draft:write - ต้องการ:
draft:write Idempotency-Key(บังคับ)- Body —
$defs/draft_discard_commandแบบปิด - คำตอบ:
{ "outcome": {...} }
Outcome:
draft_discarded/idempotent_replaydraft_conflictinvalid_requestcapability_refusedrequester_unauthorizedcontent_not_foundidempotency_key_reusedrate_limitedtemporary_failure
POST /api/plugin/v1/media
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/media”อัปโหลด media ในนามบุคคล การอัปโหลด media ปกติ ผ่านการตรวจสอบและที่เก็บเดียวกับคลัง media: ไบต์ต้องเป็นหนึ่งใน media_types ของประเภทที่ไซต์รับ (ค่าเริ่มต้นคือภาพและเอกสาร เสียงและวิดีโอเมื่อไซต์เปิดใช้) ขนาดไม่เกิน 33554432 ไบต์ บุคคลที่มอบสิทธิ์ต้องมี media:upload delegation ใดก็ได้ของ installation นี้อัปโหลดได้ ส่ง multipart/form-data ที่มี part เหล่านี้พอดี: file, delegation_id และถ้าต้องการ alt_texts (JSON object จากรหัสภาษาของไซต์ไปยังข้อความ), width, height, on_duplicate part อื่นใดคือ invalid_request ไฟล์ที่ถูกปฏิเสธคือ validation_failed พร้อม reason ของกฎ media เมื่อไซต์มีไบต์เดียวกันอยู่แล้ว on_duplicate เป็นตัวตัดสิน: ask (ค่าเริ่มต้น) ตอบ media_duplicate พร้อมไฟล์ที่มีอยู่และไม่อัปโหลดอะไร use_existing ตอบ media_reused พร้อมไฟล์ที่มีอยู่ copy อัปโหลดสำเนาแยก
- ผู้เรียก: ปลั๊กอิน,
media:write - ต้องการ:
media:write Idempotency-Key(บังคับ)- Body — multipart,
$defs/media_upload_form - คำตอบ:
{ "outcome": {...}, "data": <media> }—$defs/media;media_duplicateมี$defs/media_duplicate
Outcome:
media_uploaded/media_reused/idempotent_replaymedia_duplicate— ไซต์มีไบต์เหล่านี้อยู่แล้วและon_duplicateเป็นaskinvalid_requestcapability_refusedrequester_unauthorizedvalidation_failedlimit_exceededidempotency_key_reusedcontent_not_found— การส่งซ้ำที่ media ถูกลบไปแล้วrate_limitedtemporary_failure
POST /api/plugin/v1/launch/exchange
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/launch/exchange”แลก launch code เป็น delegation เบราว์เซอร์มาถึง management_url พร้อม dee_wan_launch BACKEND ของปลั๊กอินส่งรหัสนั้นมาที่นี่ พร้อม bearer token ของตัวเอง ภายใน 60 วินาที รหัสถูกใช้ได้ครั้งเดียว สิ่งที่ได้กลับมาคือการผูก — installation, ไซต์, action, content instance (ไม่บังคับ) และ model_ids: โมเดลใน grant ที่บุคคลนั้นอ่านได้ตอน launch ทุกรายการหรือเฉพาะรายการของตัวเอง (สำหรับ action ของเนื้อหา คือโมเดลของรายการนั้น) — และตัวตนที่ปลอดภัยต่อการแสดงผลสำหรับ session ของปลั๊กอินเอง แสดงและกระทำเฉพาะภายใน model_ids และ /delegations/:delegationId บอกสิ่งที่ยังใช้ได้ในตอนนี้ มันไม่ได้มอบ capability ใดของ Dee Wan ที่ token ของ installation ยังไม่มีอยู่แล้ว และรหัสที่ออกให้ installation อื่นจะถูกปฏิเสธ ไม่ต้องใช้ Idempotency-Key: ตัวรหัสเองใช้ได้ครั้งเดียว ดังนั้นการ retry หลัง response หายไปจะตอบ invalid_request และบุคคลนั้นต้อง launch ใหม่
- ผู้เรียก: ปลั๊กอิน พร้อม token ของ installation
- ต้องการ: ไม่มี
- Body —
$defs/launch_exchange_requestไม่มีIdempotency-Key - คำตอบ:
{ "data": <delegation> }—$defs/launch_delegation
Outcome:
invalid_request— ไม่รู้จัก, ถูกใช้แล้ว, หมดอายุ หรือออกให้ installation อื่นplugin_unauthorizedrate_limitedtemporary_failure
เปลี่ยน launch code เป็น delegation
curl -X POST "https://cms.example/api/plugin/v1/launch/exchange" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ --data '{ "code": "dwl_ExampleLaunchCodeExampleLaunchCodeExampleLa"}'{ "data": { "delegation_id": "pld_0000000000000000000000000000d1ee", "installation_id": "plg_0000000000000000000000000000d1ee", "site_id": "cdocssite00000000000000001", "action": "schedule", "instance_id": "cdocsinstance00000000000001", "model_ids": [ "cdocsmodel0000000000000001" ], "user": { "id": "cdocsuser00000000000000001", } }}เก็บ delegation_id ไว้ ทุกคำสั่งหลังจากนี้จะแนบมันไป และ core จะอ่านอำนาจของบุคคลนั้นซ้ำ
launch code ใช้ได้ครั้งเดียว
curl -X POST "https://cms.example/api/plugin/v1/launch/exchange" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ --data '{ "code": "dwl_ExampleLaunchCodeExampleLaunchCodeExampleLa"}'{ "outcome": { "code": "invalid_request", "message": "The launch code is unknown, used or expired.", "retry": false }}POST /api/plugin/v1/invocations/exchange
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/invocations/exchange”แลกรหัสการเรียกใช้เป็นข้อมูลเข้าที่ผูกไว้ core POST $defs/invocation_envelope ไปยัง endpoint ของการดำเนินการหรือนโยบายที่ประกาศไว้ ก่อนตอบ POST นั้น ปลั๊กอินส่ง code ของซองมาที่นี่พร้อม bearer token ของตัวเอง รหัสถูกใช้ได้ครั้งเดียว สิ่งที่ได้กลับคือข้อมูลที่ core บันทึกไว้: id ของการดำเนินการหรือนโยบาย โมเดลและรายการ (ถ้ามี) ตัวตนสำหรับแสดงของผู้ที่ขอ และ input ที่ผูกไว้ — ค่าของการดำเนินการ หรือสำหรับนโยบายคือ $defs/policy_facts ข้อมูลผูกของการดำเนินการกับรายการยังมี delegation_id: การมอบสิทธิ์แบบถาวรที่ผูกกับผู้เรียก ไซต์ การติดตั้ง โมเดล และรายการ เก็บไว้เหมือน launch delegation สำหรับการอ่านและคำสั่ง transition ของรายการนั้นในภายหลัง core อ่านสิทธิ์ของบุคคลนั้นใหม่ทุกครั้งที่ใช้ ข้อมูลที่ผูกของการดำเนินการระดับไซต์มี delegation แบบเดียวกับ launch แบบ manage: ไม่มีรายการ และมีโมเดลที่ได้รับสิทธิ์ซึ่งผู้เรียกอ่านได้ นโยบายได้ null core รับคำตอบของ POST จากการติดตั้งที่แลกรหัสการเรียกใช้นี้เท่านั้น และเฉพาะตอนที่การติดตั้งนั้นยังครอบคลุมอยู่ ทุกอย่างเกิดขึ้นภายใน 10 วินาที
- ผู้เรียก: ปลั๊กอิน พร้อมโทเค็นการติดตั้ง ระหว่างตอบการเรียกใช้
- ต้องมี: ไม่มี
- Body —
$defs/invocation_exchange_requestไม่มีIdempotency-Key - ตอบ:
{ "data": <binding> }—$defs/invocation_binding
ผลลัพธ์:
invalid_request— ไม่รู้จัก ใช้ไปแล้ว หมดอายุ หรือออกให้การติดตั้งอื่นcapability_refused— การติดตั้งถูกลดสิทธิ์ หรือ manifest เปลี่ยน หลังจาก core ขอplugin_unauthorizedrate_limitedtemporary_failure
รหัสการเรียกใช้ใช้ได้ครั้งเดียว และเฉพาะกับการติดตั้งที่ออกให้
curl -X POST "https://cms.example/api/plugin/v1/invocations/exchange" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp" \ -H "Content-Type: application/json" \ --data '{ "code": "dwi_ExampleInvocationCodeExampleInvocationCodeE"}'{ "outcome": { "code": "invalid_request", "message": "The invocation code is unknown, used or expired.", "retry": false }}GET /api/plugin/v1/delegations/:delegationId
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/delegations/:delegationId”อ่านว่าตอนนี้ delegation เข้าถึงอะไรได้ model_ids ของ delegation ที่ถูกจำกัดให้แคบลงตาม grant ของโมเดลปัจจุบันและตามสิ่งที่บุคคลนั้นทำได้ ในตอนนี้ โดยอ่านซ้ำในทุก request delegation แบบ manage แสดงทุกโมเดลที่บุคคลนั้นยังอ่านได้ ทุกรายการ หรือเฉพาะรายการของตัวเองภายใต้ read:own delegation แบบ content-action แสดงโมเดลของรายการนั้นตราบที่บุคคลนั้นยังอ่านรายการนั้นได้ kinds บอกชนิดของ transition ที่บุคคลนั้นทำได้กับรายการของโมเดลนั้น: installation มี workflow:publish / workflow:unpublish บุคคลนั้นแก้ไขรายการได้ และ workflow ของโมเดลมีเส้นทางชนิดนั้นที่บุคคลนั้นมีสิทธิ์ entries บอกว่าเงื่อนไขนี้เป็นจริงกับทุกรายการหรือไม่ all: บุคคลนั้นอ่านได้ทุกรายการของโมเดล และ kinds ใช้กับทุกรายการ checked: บุคคลนั้นอ่านหรือแก้ไขได้เฉพาะรายการของตัวเองที่นั่น ดังนั้น kinds คือสิ่งที่มากที่สุดที่บุคคลนั้นทำได้กับรายการที่แก้ไขได้ ให้ถาม /delegations/:delegationId/entries ว่าจะแสดงรายการใดและแต่ละรายการทำอะไรได้ ใช้เพื่อแสดงเฉพาะสิ่งที่บุคคลนั้นเห็นได้ และเสนอการย้ายเวลาหรือยกเลิก transition ที่ตั้งไว้เฉพาะเมื่อชนิดนั้นอยู่ในรายการ delegation ที่เปิดโดย credential ของ management แสดงเฉพาะชนิดที่อยู่ในเพดาน capability ของมัน คำสั่งยังถูกตรวจแยกต่างหาก
- ผู้เรียก: ปลั๊กอิน พร้อม token ของ installation
- ต้องการ: ไม่มี
- ไม่มี query และไม่มี body
- คำตอบ:
{ "data": { "delegation_id", "models": [{ "id", "slug", "kinds", "entries" }] } }—$defs/delegation_models
Outcome:
requester_unauthorized— delegation ไม่เป็นที่รู้จัก เป็นของ installation อื่น หรือบุคคลของมันถูกปิดใช้งานหรือไม่ได้เป็นสมาชิกของไซต์อีกต่อไปinvalid_requestplugin_unauthorizedrate_limitedtemporary_failure
ตอนนี้ delegation เข้าถึงอะไรได้
curl "https://cms.example/api/plugin/v1/delegations/pld_0000000000000000000000000000d1ee" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp"{ "data": { "delegation_id": "pld_0000000000000000000000000000d1ee", "models": [ { "id": "cdocsmodel0000000000000001", "slug": "article", "kinds": [ "publish", "unpublish" ], "entries": "all" } ] }}ถามอีกครั้งก่อนทุกหน้าและทุกการกระทำ บุคคลที่เสียโมเดลหรือสิทธิ์ไปก็จะเสียที่นี่ด้วย
GET /api/plugin/v1/delegations/:delegationId/entries
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/delegations/:delegationId/entries”อ่านว่าตอนนี้ delegation เข้าถึงรายการใดได้ ใช้กับโมเดลที่ /delegations/:delegationId ระบุ entries: "checked" ระบุ id ของรายการได้ไม่เกิน 100 ตัว คำตอบแสดงเฉพาะรายการที่บุคคลของ delegation อ่านได้ ในตอนนี้ แต่ละรายการพร้อมชนิดของ transition ที่บุคคลนั้นทำได้กับรายการนั้น: kinds ของโมเดลเมื่อบุคคลนั้นแก้ไขรายการนั้นได้ ไม่เช่นนั้นไม่มีเลย รายการของไซต์อื่น รายการในถังขยะ รายการของโมเดลที่อยู่นอก model_ids ของ delegation หรือนอก grant ปัจจุบัน รายการที่อยู่นอก translation group ของ delegation แบบ content-action หรือรายการที่บุคคลนั้นอ่านไม่ได้ จะถูกตัดออกโดยไม่บอกเหตุผล ความเป็นเจ้าของและสิทธิ์ถูกอ่านซ้ำในทุก request ดังนั้นให้ถามอีกครั้งก่อนทุกหน้าและทุกการกระทำ เก็บคำตอบไว้เฉพาะบุคคลนั้น: อย่าแสดงรายการที่คำตอบตัดออกเด็ดขาด
- ผู้เรียก: ปลั๊กอิน พร้อม token ของ installation
- ต้องการ: ไม่มี
instance_id— 1 ถึง 100 ครั้ง แต่ละตัวเป็น id ของรายการ ค่าซ้ำนับครั้งเดียว ไม่มี query อื่นและไม่มี body- คำตอบ:
{ "data": { "delegation_id", "entries": [{ "instance_id", "model_id", "kinds" }] } }—$defs/delegation_entries
Outcome:
invalid_request— ไม่มีinstance_idมีเกิน 100 ตัว มีตัวที่รูปแบบไม่ถูกต้อง หรือมี parameter อื่นrequester_unauthorized— delegation ไม่เป็นที่รู้จัก เป็นของ installation อื่น หรือบุคคลของมันถูกปิดใช้งานหรือไม่ได้เป็นสมาชิกของไซต์อีกต่อไปplugin_unauthorizedrate_limitedtemporary_failure
ตอนนี้ delegation เข้าถึงรายการใดในชุดนี้ได้
curl "https://cms.example/api/plugin/v1/delegations/pld_0000000000000000000000000000d1ee/entries?instance_id=cdocsinstance00000000000001&instance_id=cotherinstance0000000000001" \ -H "Authorization: Bearer dwp_ExampleTokenNotRealExampleTokenNotRealExamp"{ "data": { "delegation_id": "pld_0000000000000000000000000000d1ee", "entries": [ { "instance_id": "cdocsinstance00000000000001", "model_id": "cdocsmodel0000000000000001", "kinds": [ "publish", "unpublish" ] } ] }}รายการของไซต์อื่นถูกตัดออกโดยไม่บอกเหตุผล แสดงเฉพาะรายการที่อยู่ในคำตอบ
POST /api/plugin/v1/content
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/content”สร้างรายการที่บันทึกแล้ว ตรวจด้วย lifecycle ปกติ delegation แบบ manage ต้องรวมโมเดลนี้
- ผู้เรียก: ปลั๊กอินในนามบุคคลที่มอบสิทธิ์
- ต้องการ:
content:createและสิทธิ์สร้างปัจจุบัน - ต้องมี
Idempotency-Key - เนื้อหา:
$defs/content_create_command. - คำตอบ:
content_savedพร้อม$defs/content_save_result.
ผลลัพธ์:
content_saved/idempotent_replaycapability_refused/requester_unauthorized/content_not_found/validation_failed/idempotency_key_reused
DELETE /api/plugin/v1/content/:instanceId
หัวข้อที่มีชื่อว่า “DELETE /api/plugin/v1/content/:instanceId”ย้ายรายการไปถังขยะ ใช้ lifecycle กับทั้งรายการ ต้องยกเลิกเผยแพร่ก่อน ตรวจเวอร์ชันปัจจุบันแบบ atomic
- ผู้เรียก: ปลั๊กอินในนามบุคคลที่มอบสิทธิ์
- ต้องการ:
content:deleteและสิทธิ์ลบปัจจุบัน - ต้องมี
Idempotency-Key - เนื้อหา:
$defs/content_delete_command. - คำตอบ:
content_deletedพร้อมผลการย้ายไปถังขยะตามปกติ
ผลลัพธ์:
content_deleted/idempotent_replaycapability_refused/requester_unauthorized/content_not_found/version_conflict/validation_failed/idempotency_key_reused
GET /api/plugin/v1/content/:instanceId/versions
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/content/:instanceId/versions”แสดงเวอร์ชันที่เก็บไว้ แบ่งหน้า ID เวอร์ชันแบบจำกัด ตรวจความเป็นเจ้าของรายการหลัก
- ผู้เรียก: ปลั๊กอินในนามบุคคลที่มอบสิทธิ์
- ต้องการ:
content:readและสิทธิ์อ่านประวัติปัจจุบัน - Query: ต้องมี
delegation_id;limit,cursorไม่บังคับ - คำตอบ:
$defs/content_versions.
ผลลัพธ์:
- 200
capability_refused/requester_unauthorized/content_not_found/invalid_request
GET /api/plugin/v1/content/:instanceId/versions/:versionId
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/content/:instanceId/versions/:versionId”อ่านเวอร์ชันที่เก็บไว้ snapshot มาตรฐานถูกจำกัดตามสิทธิ์ฟิลด์ ภาษา และความเป็นเจ้าของ เมื่อส่ง include_dependencies=true คำตอบจะเพิ่ม dependency_refs: [{ instance_id, locale }] และ dependencies_incomplete โดยรวมความสัมพันธ์ทั่วไป ความสัมพันธ์แยกภาษา ความสัมพันธ์ในคอมโพเนนต์ซ้อน และส่วนที่ใช้ร่วมกันซึ่งฝังไว้ ระบบใช้สิทธิ์ปัจจุบันของผู้ใช้และโมเดลที่อนุญาตให้ปลั๊กอินเข้าถึง ไม่ส่งตัวระบุของรายการที่อ่านไม่ได้ และระบุ dependencies_incomplete: true แทน รายการอ้างอิงนี้ไม่ให้สิทธิ์อ่านหรือเผยแพร่เพิ่ม
- ผู้เรียก: ปลั๊กอินในนามบุคคลที่มอบสิทธิ์
- ต้องการ:
content:readและสิทธิ์อ่านประวัติปัจจุบัน - Query: ต้องมี
delegation_id - พารามิเตอร์เสริมคือ
include_dependencies=trueและdependency_locale=<code>การระบุภาษาต้องใช้ร่วมกับพารามิเตอร์แรก และเป็นภาษาของไซต์ที่ผู้ใช้อ่านได้ หากไม่ระบุภาษา ระบบตรวจภาษาของเวอร์ชันที่อ่านได้ - คำตอบ:
{data: <content_version>};$defs/content_version.
ผลลัพธ์:
- 200
capability_refused/requester_unauthorized/content_not_found/invalid_request
GET /api/plugin/v1/media/:mediaId
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/media/:mediaId”อ่าน metadata ของสื่อที่มีอยู่ ใช้บริการทรัพยากรสื่อร่วมกันสำหรับสื่อของไซต์
- ผู้เรียก: ปลั๊กอินในนามบุคคลที่มอบสิทธิ์
- ต้องการ:
media:readและสิทธิ์อ่านคลังสื่อปัจจุบัน - Query: ต้องมี
delegation_id - คำตอบ:
{data: <media>}พร้อม metadata สำหรับแสดงผล
ผลลัพธ์:
- 200
capability_refused/requester_unauthorized/content_not_found/invalid_request
GET /api/plugin/v1/media/:mediaId/bytes
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/media/:mediaId/bytes”อ่านไบต์ของสื่อที่มีอยู่ ใช้ reader ของ provider ร่วมกันสำหรับไฟล์สาธารณะและส่วนตัวของไซต์ การอ้างอิงภายนอกไม่มีไบต์ในไซต์ คำตอบส่วนตัวห้าม cache
- ผู้เรียก: ปลั๊กอินในนามบุคคลที่มอบสิทธิ์
- ต้องการ:
media:readและสิทธิ์อ่านคลังสื่อปัจจุบัน - Query: ต้องมี
delegation_id - คำตอบ: ไฟล์ไบนารีพร้อม content type/disposition ที่ปลอดภัย
ผลลัพธ์:
- 200
capability_refused/requester_unauthorized/content_not_found/limit_exceeded/temporary_failure
PUT /api/plugin/v1/media/:mediaId
หัวข้อที่มีชื่อว่า “PUT /api/plugin/v1/media/:mediaId”แก้ metadata ของสื่อ ใช้การตรวจร่วมกันและเขียนแบบ atomic พร้อม idempotency
- ผู้เรียก: ปลั๊กอินในนามบุคคลที่มอบสิทธิ์
- ต้องการ:
media:updateและสิทธิ์media:updateปัจจุบัน - ต้องมี
Idempotency-Key - เนื้อหา:
$defs/media_update_command. - คำตอบ:
media_updated,{id}.
ผลลัพธ์:
media_updated/idempotent_replaycapability_refused/requester_unauthorized/content_not_found/validation_failed/idempotency_key_reused
POST /api/plugin/v1/content/:instanceId/futures
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/content/:instanceId/futures”เตรียมเวอร์ชันอนาคตแยกจากฉบับร่างปกติ สร้างเวอร์ชันที่บันทึกไว้จากฉบับร่างปัจจุบันของรายการ แล้วผูกกับการติดตั้งปลั๊กอินและรีลีสนี้ การเรียกซ้ำด้วยการติดตั้ง รีลีส และรายการหลักเดิมจะคืนเวอร์ชันเดิม โดยไม่เปลี่ยนฉบับร่างปกติหรือค่า EAV ผู้มอบสิทธิ์ยังต้องอ่านและแก้ไขรายการได้ หากระบุ locale ระบบจะตรวจสิทธิ์ของภาษานั้นด้วย ชื่อจะถูกตัดช่องว่างหัวท้ายและยาวได้ไม่เกิน 120 อักขระ แก้ไขเวอร์ชันนี้ใน Dee Wan ผ่าน editor_url โดยมี revision และการตรวจเวอร์ชันของตัวเอง เฉพาะคำสั่งเผยแพร่ที่มีสิทธิ์ปัจจุบันเท่านั้นที่ตรึงเวอร์ชันเพื่อดำเนินการได้
- ผู้เรียก: ปลั๊กอินแทนผู้มอบสิทธิ์
- ต้องมี:
workflow:releaseและสิทธิ์แก้ไขที่ได้รับมอบและยังใช้ได้ - Body —
$defs/future_create_commandเป็นรูปแบบปิด ต้องมีdelegation_id,release_id,nameและระบุlocaleได้ ไม่ต้องใช้Idempotency-Key - คำตอบ: 201
{ "data": <future with editor_url> }—$defs/future_createdรวมถึงเมื่อเรียกซ้ำแล้วได้เวอร์ชันเดิม
Outcome:
invalid_requestcapability_refused/requester_unauthorized/content_not_foundvalidation_failed/version_conflict/transition_refused/temporary_failure
GET /api/plugin/v1/content/:instanceId/futures/:futureId
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/content/:instanceId/futures/:futureId”อ่านเวอร์ชันอนาคตของการติดตั้งนี้ เว็บไซต์ รายการหลัก และการติดตั้งของเวอร์ชันต้องตรงกับคำขอ คำตอบมีสถานะ revision, current_version_id และข้อมูลสรุปรายการตามสิทธิ์ปัจจุบัน โดย current_version_id ในข้อมูลสรุปอ้างถึงเวอร์ชันนี้ ระบบไม่คืนค่าฟิลด์ที่ยังไม่ผ่านการตรวจสิทธิ์ ข้อมูลสรุป workflow แสดงการเปลี่ยนสถานะที่ทำได้ รวมถึงการเผยแพร่ซ้ำจากเวอร์ชันอนาคตเมื่อมีสิทธิ์ หากต้องการเผยแพร่ ให้ส่ง future_draft_id คู่กับ expected_future_revision และกำหนด expected_current_version_id เป็นเวอร์ชันที่บันทึกไว้ของฉบับนี้ ก่อนตรึงและเผยแพร่ ระบบจะตรวจฟิลด์บังคับ งานอนุมัติ workflow ความสัมพันธ์ และสื่อ โดยไม่เปลี่ยนฉบับร่างปกติ หากไม่ทราบผลของคำสั่ง ให้ส่งคำสั่ง เวอร์ชัน และคีย์เดิมซ้ำ
- ผู้เรียก: ปลั๊กอินแทนผู้มอบสิทธิ์
- ต้องมี:
workflow:releaseและสิทธิ์อ่านที่ได้รับมอบและยังใช้ได้ - Query: ต้องมี
delegation_id—$defs/future_read_query - คำตอบ: 200
{ "data": { "future": <future>, "summary": <content_summary> } }—$defs/future_read
Outcome:
invalid_requestcapability_refused/requester_unauthorized/content_not_found
POST /api/plugin/v1/releases/commit
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/releases/commit”ใช้รีลีสที่ประสานกัน. วางแผนสถานะสุดท้ายของคำสั่งไม่เกิน 25 รายการในเว็บไซต์เดียว ตรวจสิทธิ์ ขอบเขตโมเดล workflow เวอร์ชัน ภาษา และความสัมพันธ์ ข้อมูลเผยแพร่ เหตุการณ์ workflow และบันทึกการเรียกซ้ำ commit ในชุดคำสั่งที่มี guard เดียวในฐานข้อมูลเว็บไซต์ หรือไม่เปลี่ยนเลย รองรับหลายภาษาที่ต่างกันของกลุ่มเดียว แต่ปฏิเสธขอบเขตที่ทับกัน การส่งแจ้งเตือนและ redirect อัตโนมัติเกิดหลัง commit
- ผู้เรียก: ปลั๊กอินแทนบุคคลที่มอบสิทธิ์
- ต้องมี:
workflow:release - ต้องมี
Idempotency-Keybody คือ$defs/release_command - คำตอบ:
release_appliedหรือidempotent_replayพร้อม$defs/release_result
Outcome:
operation_appliedหรือผลการบันทึกหรือรีลีสที่ระบุไว้capability_refused,requester_unauthorized,validation_failed,version_conflict,limit_exceeded,temporary_failure
GET /api/plugin/v1/comments
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/comments”อ่านความคิดเห็นผู้เข้าชม. ใช้บริการอ่านเพื่อจัดการความคิดเห็นเดิม และการมองเห็นโมเดลกับรายการปัจจุบัน
- ผู้เรียก: ปลั๊กอินแทนบุคคลที่มอบสิทธิ์
- ต้องมี:
comments:read - query มี
delegation_idและตัวกรองรายการความคิดเห็นของ API การจัดการเดิม - คำตอบ: รายการความคิดเห็นที่มีขีดจำกัด โดยไม่เปิดเผยอีเมลส่วนตัว
Outcome:
operation_appliedหรือผลการบันทึกหรือรีลีสที่ระบุไว้capability_refused,requester_unauthorized,validation_failed,version_conflict,limit_exceeded,temporary_failure
POST /api/plugin/v1/comments/moderate
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/comments/moderate”จัดการความคิดเห็นผู้เข้าชม. ใช้บริการจัดการความคิดเห็นเดิม ไม่สร้างความยินยอมขึ้นเอง และปฏิเสธสถานะเก่าของแต่ละความคิดเห็น
- ผู้เรียก: ปลั๊กอินแทนบุคคลที่มอบสิทธิ์
- ต้องมี:
comments:moderate - ต้องมี
Idempotency-Keybody มีdelegation_id,to,comments: [{id, expected}] - คำตอบ: ผลการจัดการความคิดเห็นตามปกติ
Outcome:
operation_appliedหรือผลการบันทึกหรือรีลีสที่ระบุไว้capability_refused,requester_unauthorized,validation_failed,version_conflict,limit_exceeded,temporary_failure
GET /api/plugin/v1/redirects
หัวข้อที่มีชื่อว่า “GET /api/plugin/v1/redirects”อ่าน redirect. ต้องมีสิทธิ์ site:settings ปัจจุบัน
- ผู้เรียก: ปลั๊กอินแทนบุคคลที่มอบสิทธิ์
- ต้องมี:
redirects:read - query มี
delegation_id - คำตอบ: เฉพาะ
revisionและredirectsที่ยอมรับแล้ว
Outcome:
operation_appliedหรือผลการบันทึกหรือรีลีสที่ระบุไว้capability_refused,requester_unauthorized,validation_failed,version_conflict,limit_exceeded,temporary_failure
POST /api/plugin/v1/redirects/review
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/redirects/review”ตรวจรูปแบบ redirect. ใช้การตรวจรูปแบบกับที่อยู่ปัจจุบันแบบเดียวกับหน้าผู้ดูแล
- ผู้เรียก: ปลั๊กอินแทนบุคคลที่มอบสิทธิ์
- ต้องมี:
redirects:write - body มี
delegation_id,redirects - คำตอบ: ผลการตรวจรูปแบบและ digest ที่ต้องใช้ตอนบันทึก
Outcome:
operation_appliedหรือผลการบันทึกหรือรีลีสที่ระบุไว้capability_refused,requester_unauthorized,validation_failed,version_conflict,limit_exceeded,temporary_failure
PUT /api/plugin/v1/redirects
หัวข้อที่มีชื่อว่า “PUT /api/plugin/v1/redirects”แก้ redirect. รับเฉพาะการเปลี่ยน redirect ใช้การตรวจรีวิชัน path ชนกัน วงวน และการตรวจรูปแบบเดิม
- ผู้เรียก: ปลั๊กอินแทนบุคคลที่มอบสิทธิ์
- ต้องมี:
redirects:write - ต้องมี
Idempotency-Keybody มีdelegation_id,expected_revision,redirectsและredirect_review_digestที่ไม่บังคับ - คำตอบ: เฉพาะ
revisionและredirectsที่ยอมรับแล้ว
Outcome:
operation_appliedหรือผลการบันทึกหรือรีลีสที่ระบุไว้capability_refused,requester_unauthorized,validation_failed,version_conflict,limit_exceeded,temporary_failure
POST /api/plugin/v1/content/:instanceId/restore
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/content/:instanceId/restore”กู้รายการจากถังขยะ. กู้เป็นฉบับร่างผ่านการตรวจวงจรเนื้อหา ที่อยู่ สิทธิ์ฟิลด์และภาษา รวมถึงความเป็นเจ้าของเดิม
- ผู้เรียก: ปลั๊กอินแทนบุคคลที่มอบสิทธิ์
- ต้องมี:
content:restore - ต้องมี
Idempotency-Keybody มีdelegation_id - คำตอบ: ผลการกู้จากถังขยะตามปกติ
Outcome:
operation_appliedหรือผลการบันทึกหรือรีลีสที่ระบุไว้capability_refused,requester_unauthorized,validation_failed,version_conflict,limit_exceeded,temporary_failure
POST /api/plugin/v1/media/:mediaId/remove
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/media/:mediaId/remove”ลบสื่อที่ไม่ใช้งาน. ต้องมีสิทธิ์ media:delete ปัจจุบัน เนื้อหาปัจจุบัน ประวัติที่เก็บไว้ และการอ้างอิงที่เพิ่มพร้อมกันป้องกันการลบสื่อที่ยังใช้งาน การล้างไฟล์ในที่เก็บแยกจากการลบข้อมูล
- ผู้เรียก: ปลั๊กอินแทนบุคคลที่มอบสิทธิ์
- ต้องมี:
media:delete - ต้องมี
Idempotency-Keybody มีdelegation_id - คำตอบ: ผลการลบสื่อตามปกติและสถานะการล้างไฟล์
Outcome:
operation_appliedหรือผลการบันทึกหรือรีลีสที่ระบุไว้capability_refused,requester_unauthorized,validation_failed,version_conflict,limit_exceeded,temporary_failure
POST /api/plugin/v1/mail/send
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/mail/send”ส่งแม่แบบอีเมลที่อนุมัติ ต้องมีสิทธิ์ site:plugins ปัจจุบันและแม่แบบที่ผู้ดูแลตรวจแล้ว แบบระบุที่อยู่ใช้ delegation แบบ manage และไม่ส่ง instance_id สำหรับ entry_author หรือ entry_assignee ให้ส่ง instance_id ของรายการที่อยู่ในขอบเขตโมเดลและรายการของ installation และ delegation โดยผู้เริ่มส่งต้องยังอ่านรายการได้ ใช้ delegation แบบ manage หรือของการทำงานกับรายการที่ตรงกันได้ entry_author เลือกบัญชีที่สร้างรายการที่เลือกใน CMS (content_instance.created_by_id) ไม่ใช่ผู้เขียนบล็อกสาธารณะ โปรไฟล์ที่เชื่อมโยง หรือผู้แก้ไขล่าสุด ส่วน entry_assignee เลือกผู้ได้รับมอบหมายปัจจุบันในเวิร์กโฟลว์ของรายการนั้น (content_workflow.assigned_to_id) บัญชีผู้รับต้องเปิดใช้งาน มีสิทธิ์เข้าถึงเว็บไซต์ในปัจจุบัน และอ่านรายการได้ ผู้ดูแลระบบสูงสุดที่เปิดใช้งานอาจเข้าเงื่อนไขได้โดยไม่ต้องมีบทบาทแยกสำหรับเว็บไซต์นี้ หากไม่มีบัญชีที่เข้าเงื่อนไขจะได้ validation_failed
ปลั๊กอินระบุอีเมล ID บัญชี วิธีเลือกผู้รับ หัวเรื่อง ข้อความ หรือข้อมูลรับรองผู้ให้บริการเองไม่ได้ คำตอบไม่เปิดเผยที่อยู่ จำกัด body ที่ 16384 ไบต์ และค่าทดแทนที่ประกาศไม่เกิน 16 ค่า ค่าละ 1000 อักขระ หลังแทนค่า หัวเรื่องต้องมี 1–200 อักขระโดยไม่ขึ้นบรรทัด และข้อความไม่เกิน 12000 อักขระ หากเกินจะปฏิเสธก่อนเก็บบันทึกการเรียกซ้ำ
คำขอที่รับไว้จะเก็บข้อความและบัญชีผู้รับ การลองใหม่ด้วยคีย์เดิมใช้ข้อมูลนี้ แม้ผู้เขียน ผู้ได้รับมอบหมาย หรือแม่แบบเปลี่ยนไป ระบบตรวจสิทธิ์ผู้เริ่มส่งและผู้รับเดิมในการอ่านรายการ สถานะบัญชี และอีเมลที่ต้องยังตรงกัน หากเปลี่ยนรายการหรือค่าทดแทนโดยใช้คีย์เดิมจะถูกปฏิเสธ การลองใหม่ใช้ ID ข้อความเดิม และผลจากผู้ให้บริการที่ยังไม่ยืนยันยังลองใหม่ได้
- ผู้เรียก: ปลั๊กอินแทนบุคคลที่มอบสิทธิ์
- ต้องมี:
mail:send - ต้องมี
Idempotency-Keybody คือ$defs/mail_command - คำตอบ:
operation_appliedหรือidempotent_replay,{sent:true}ยืนยันเพียงว่าผู้ให้บริการรับแล้ว ไม่ใช่ว่าเข้ากล่องจดหมายแล้ว
Outcome:
operation_appliedหรือผลการบันทึกหรือรีลีสที่ระบุไว้capability_refused,requester_unauthorized,validation_failed,version_conflict,limit_exceeded,temporary_failure
POST /api/plugin/v1/content/:instanceId/renderer-metadata
หัวข้อที่มีชื่อว่า “POST /api/plugin/v1/content/:instanceId/renderer-metadata”บันทึกเมทาดาทาตัวแสดงผล. เขียนเฉพาะข้อมูลเสริมที่ installation นี้ประกาศสำหรับภาษาเดียว เป็นเวอร์ชันที่บันทึกใหม่ตามปกติ การเผยแพร่เป็นอีกขั้นตอน ค่า SEO หลัก การยืนยันเว็บไซต์ และลิงก์ภาษาจากระบบหลักมีลำดับความสำคัญสูงกว่า โดยไม่เพิ่มสคริปต์หรือการเรียก CMS ขณะเว็บไซต์ทำงาน
- ผู้เรียก: ปลั๊กอินแทนบุคคลที่มอบสิทธิ์
- ต้องมี:
renderer:metadata - ต้องมี
Idempotency-Keybody คือ$defs/renderer_metadata_command - คำตอบ: ผล
content_savedตามปกติ
Outcome:
operation_appliedหรือผลการบันทึกหรือรีลีสที่ระบุไว้capability_refused,requester_unauthorized,validation_failed,version_conflict,limit_exceeded,temporary_failure
Outcome
หัวข้อที่มีชื่อว่า “Outcome”คำสั่งและการปฏิเสธทุกครั้งตอบด้วย outcome envelope — รหัสสำหรับเครื่องและข้อความสำหรับมนุษย์
การอ่านที่สำเร็จ /launch/exchange และ /invocations/exchange ไม่ได้ตอบเช่นนั้น: พวกมันตอบ { "data": … }
(และ "next" บนหน้าของ list) โดยไม่มี outcome การปฏิเสธสามแบบมี data ด้วย: validation_failed
ระบุกฎ ($defs/validation_detail) draft_conflict มี draft ปัจจุบันใน data.current และ
media_duplicate มีไฟล์ที่มีอยู่แล้วและจำนวนสำเนาของมัน ($defs/media_duplicate)
{ "outcome": { "code": "transition_applied", "message": "…", "retry": false }, "data": {}}แยกกรณีตาม code หลังตรวจ code, HTTP status, ค่า retry และ message ที่เป็นข้อความแล้ว ข้อความมีไว้สำหรับคนและไม่ใช่ค่าคงที่ ค่า retry เพียงอย่างเดียวไม่ได้ทำให้คำตอบเชื่อถือได้
| HTTP | รหัส | Retry | ความหมาย |
|---|---|---|---|
| 200 | release_applied |
ไม่ | ใช้รีลีสแบบอะตอมมิกแล้ว |
| 200 | operation_applied |
ไม่ | ใช้ operation แล้ว |
| 200 | transition_applied |
ไม่ | transition ถูกนำไปใช้แล้ว |
| 200 | idempotent_replay |
ไม่ | คำสั่งนี้ถูกนำไปใช้แล้ว ผลลัพธ์แรกถูกส่งกลับ |
| 200 | content_saved |
ไม่ | ค่าฟิลด์ถูกบันทึกเป็นเวอร์ชันใหม่ |
| 200 | content_deleted |
ไม่ | ย้ายรายการไปถังขยะแล้ว |
| 200 | draft_saved |
ไม่ | working draft ถูกบันทึกแล้ว |
| 200 | draft_discarded |
ไม่ | working draft ถูกทิ้งแล้ว |
| 200 | media_uploaded |
ไม่ | media ถูกอัปโหลดแล้ว |
| 200 | media_reused |
ไม่ | ไซต์มีไฟล์นี้อยู่แล้ว ส่ง media ที่มีอยู่กลับไปและไม่ได้อัปโหลดอะไร |
| 200 | media_updated |
ไม่ | อัปเดตข้อมูลสื่อแล้ว |
| 200 | proposal_created |
ไม่ | ข้อเสนอถูกสร้างแล้ว ไม่มีอะไรเปลี่ยนจนกว่าบุคคลจะนำไปใช้ |
| 400 | invalid_request |
ไม่ | request ไม่ถูกต้องสำหรับ protocol v1 |
| 401 | plugin_unauthorized |
ไม่ | token ของ installation หายไป, ไม่รู้จัก, ถูก disable หรือถูก revoke |
| 403 | capability_refused |
ไม่ | installation นี้ไม่ได้รับ grant capability หรือโมเดลนั้น |
| 403 | requester_unauthorized |
ไม่ | บุคคลที่ร้องขอสิ่งนี้ไม่มีอำนาจที่ต้องใช้อีกต่อไป |
| 404 | content_not_found |
ไม่ | ไม่มีเนื้อหานี้ในขอบเขตของ installation นี้ |
| 409 | scheduled_target_stale |
ไม่ | version ที่ถูก pin ไม่ใช่ตัวที่ transition นี้จะเคลื่อนย้ายอีกต่อไป |
| 409 | workflow_conflict |
ไม่ | เนื้อหาเคลื่อนผ่าน workflow ของมันไปแล้วหลังจากที่มีการร้องขอนี้ |
| 409 | dependent_content |
ไม่ | มีเนื้อหาอื่นที่พึ่งพารายการนี้ บุคคลต้องตรวจทานการยกเลิกการเผยแพร่ใน Dee Wan |
| 409 | idempotency_key_reused |
ไม่ | idempotency key นี้ถูกใช้ไปแล้วกับคำสั่งอื่น |
| 409 | version_conflict |
ไม่ | รายการเปลี่ยนหลังเวอร์ชันที่ pin ไว้ อ่านใหม่ก่อนเขียน |
| 409 | media_duplicate |
ไม่ | ไซต์มีไฟล์นี้อยู่แล้ว ไม่ได้อัปโหลดอะไร ส่ง on_duplicate เพื่อใช้ไฟล์นั้นหรืออัปโหลดสำเนา |
| 409 | draft_conflict |
ไม่ | working draft เปลี่ยนหลัง revision ที่ pin ไว้ อ่านใหม่ก่อนเขียน |
| 413 | limit_exceeded |
ไม่ | คำขอเกินขีดจำกัดขนาดหรือจำนวน |
| 422 | transition_unavailable |
ไม่ | transition นั้นใช้ไม่ได้จาก state ปัจจุบันของเนื้อหา |
| 422 | transition_refused |
ไม่ | lifecycle ปฏิเสธ transition นี้ ไม่มีอะไรถูกเปลี่ยน |
| 422 | validation_failed |
ไม่ | กฎของเนื้อหาปฏิเสธค่าเหล่านี้ ไม่มีอะไรถูกเปลี่ยน |
| 429 | rate_limited |
ใช่ | request มากเกินไปสำหรับ installation นี้ |
| 503 | temporary_failure |
ใช่ | Dee Wan ดำเนินการ request ไม่สำเร็จ ไม่มีสิ่งใดที่ทราบว่าถูกเปลี่ยน |
กฎการ retry
หัวข้อที่มีชื่อว่า “กฎการ retry”- ตรวจ structured outcome ก่อนใช้กฎสำรองตาม HTTP status ค่า
codeที่รู้จัก HTTP status และretryแบบ boolean ต้องตรงกับตาราง และmessageต้องเป็นข้อความ หากไม่ตรงหรือสมาชิกoutcomeผิดรูปแบบ ให้จบด้วยuntrusted_responseแม้ status จะลองใหม่ได้ rate_limited(429) และtemporary_failure(503) ที่ถูกต้องให้ลองใหม่ได้ core ส่งtemporary_failureเฉพาะกับ 503 ไม่ส่งกับ 500, 502 หรือ 504- คำตอบขาเข้า 429/500/502/503/504 ที่ไม่มีสมาชิก
outcomeให้ลองใหม่ได้ รวมถึง body ว่าง ไม่ใช่ JSON และข้อผิดพลาดจากตัวกลาง หากเป็น status อื่น body ของคำสั่งที่ไม่มี outcome ถูกต้องให้จบด้วยuntrusted_responseและไม่ตาม redirect - ข้อผิดพลาดเครือข่าย timeout และการอ่านคำตอบล้มเหลวให้ลองใหม่เป็น
no_responseสิ่งเหล่านี้ไม่ได้พิสูจน์ว่าไม่มีผลเกิดขึ้น token ที่เก็บไว้แต่อ่านไม่ได้ให้จบด้วยtoken_unreadable - เคารพ
Retry-Afterบนคำตอบที่ลองใหม่ได้: วินาทีจำนวนเต็มไม่ติดลบหรือวันที่ HTTP มาตรฐาน (IMF-fixdate) วันที่ผ่านมาแล้วให้หน่วงศูนย์ ค่าผิดรูปแบบให้ใช้ exponential backoff แบบมีขอบเขตพร้อม jitter หากเวลารอเกินเพดาน หรือเกินจำนวนครั้งหรืออายุ ให้จบด้วยretry_exhausted - ความสำเร็จที่ถูกต้องคือ code 200:
release_applied,operation_applied,transition_applied,idempotent_replay,content_saved,content_deleted,draft_saved,draft_discarded,media_uploaded,media_reused,media_updated,proposal_createdoutcome อื่นที่ถูกต้องแต่ลองใหม่ไม่ได้คือการปฏิเสธขั้นสุดท้ายด้วย code เดิม - ใช้ body และ
Idempotency-Keyเดิมทุกไบต์เมื่อ retry หรือกู้คืน lease คำขออาจซ้ำ แต่ผลต้องเกิดไม่เกินหนึ่งครั้งภายในช่วงเก็บ key เฉพาะผู้ครอง lease ปัจจุบันเท่านั้นที่เริ่มคำสั่งได้ และ deadline ของคำขอต้องก่อน lease หมดอายุ ห้ามตั้งใจส่ง delivery เดียวกันพร้อมกัน timeout ไม่ได้พิสูจน์ว่าคำขอระยะไกลหยุดแล้ว - กำหนดเพดานอายุให้น้อยกว่า 30 วันมาก เมื่อพ้นช่วงเก็บข้อมูล core จะลืม key เมื่อถึงขีดจำกัดการลองใหม่แล้ว ห้ามส่งคำขอเพิ่ม ผลที่ยังไม่ได้รับการยืนยันยังถือว่าไม่ทราบ ให้ตรวจเนื้อหาก่อนสร้างรายการกำหนดเวลาใหม่ด้วย key ใหม่
- กฎนี้ใช้กับการ retry คำสั่ง การอ่านที่สำเร็จยังต้องมีรูปแบบข้อมูลตามเอกสาร
/launch/exchangeใช้ code ได้ครั้งเดียวและไม่ควรลองซ้ำอัตโนมัติเมื่อคำตอบหาย
Route ด้านการดูแลระบบ
หัวข้อที่มีชื่อว่า “Route ด้านการดูแลระบบ”route ฝั่งเบราว์เซอร์เหล่านี้ต้องมี session ของผู้ใช้และ header เว็บไซต์ การติดตั้ง มอบสิทธิ์
เปลี่ยนโทเค็น ถอนการติดตั้ง และตั้งค่าเทมเพลตอีเมลต้องมี site:plugins ส่วนมุมมองที่มีชื่อ
ใช้สิทธิ์โมเดลและสิทธิ์ระบบปัจจุบันที่ประกาศไว้แทน โทเค็นปลั๊กอินเรียก route เหล่านี้ไม่ได้
เอกสารส่วนนี้อธิบายให้ผู้เขียนปลั๊กอินเข้าใจอินเทอร์เฟซของโฮสต์
route ที่ทำ mutation แต่ละตัวจะเขียน audit entry และจะปฏิเสธ
(503 audit_unavailable) แทนที่จะ mutate โดยไม่มี audit การปฏิเสธจะตอบ { "error": <text>, "reason": <code> }
ให้แยกกรณีตาม reason ไม่ใช่ตาม error missing_permission ยังระบุสิทธิ์ที่ต้องใช้ไว้ใน required ด้วย
GET /api/plugins/role-actions
หัวข้อที่มีชื่อว่า “GET /api/plugins/role-actions”แสดงการทำงานที่ปลั๊กอินที่ติดตั้งประกาศไว้สำหรับกำหนดให้บทบาท รหัสการทำงานมี namespace ของปลั๊กอินกำกับ การทำงานที่ถูกลบหรือไม่มีคำประกาศไม่ให้สิทธิ์เรียกใช้งาน
- ผู้เรียก: ผู้ใช้ที่มีสิทธิ์จัดการบทบาท
- สิทธิ์ที่ต้องมี:
role:manage - คำตอบ:
{ "data": [{ "plugin_id", "plugin_name", "action_id", "action", "label" }] } - รหัสคำตอบ:
200,403
GET /api/plugins/views
หัวข้อที่มีชื่อว่า “GET /api/plugins/views”รายการพื้นที่ทำงานปลั๊กอินที่ใช้ได้. เมนู ตำแหน่งบนแดชบอร์ด และ route โดยตรงใช้การตรวจสิทธิ์ปัจจุบันเดียวกัน เฟรมแยกจาก origin ของหน้าผู้ดูแล
- ผู้เรียก: ผู้ใช้ที่ลงชื่อเข้าใช้
- ต้องมี: capability ที่ประกาศของมุมมองในปัจจุบัน และโมเดลที่ได้รับสิทธิ์และอ่านได้
- คำตอบ: มุมมองที่มีชื่อและประกาศเฟรมที่ตรวจแล้ว
Outcome:
- 200
GET /api/plugins/views/:installationId/:viewId
หัวข้อที่มีชื่อว่า “GET /api/plugins/views/:installationId/:viewId”เปิดพื้นที่ทำงานปลั๊กอินที่ใช้ได้. มุมมองที่ไม่มีให้ใช้ ถูกปิด ไม่ได้รับสิทธิ์ หรืออ่านไม่ได้ ตอบ not_found
- ผู้เรียก: ผู้ใช้ที่ลงชื่อเข้าใช้
- ต้องมี: สิทธิ์ปัจจุบันเดียวกับที่ใช้ในรายการ
- คำตอบ: มุมมองที่ตรวจแล้วหนึ่งรายการ
Outcome:
- 200
- 404
PUT /api/plugins/:id/mail-templates
หัวข้อที่มีชื่อว่า “PUT /api/plugins/:id/mail-templates”ตรวจเทมเพลตอีเมลและผู้รับ. รับเฉพาะ ID เทมเพลตและค่าทดแทนที่ประกาศ การตั้งค่าที่อนุมัติเก็บแยกต่อ installation และบันทึกในการตรวจสอบ
- ผู้เรียก: ผู้ดูแลเว็บไซต์
- ต้องมี: site:plugins
- map จาก ID แม่แบบที่ประกาศไปยัง
{recipient_source?, recipients, subject, text}: ไม่เกิน 8 แม่แบบ หากไม่ระบุrecipient_sourceหรือใช้fixedต้องมีที่อยู่ที่อนุมัติ 1–8 ราย ส่วนentry_authorและentry_assigneeต้องไม่มีที่อยู่ (recipients: []) หัวเรื่อง 1–200 อักขระโดยไม่ขึ้นบรรทัด และข้อความ 1–12000 อักขระ - คำตอบ: การตั้งค่าเทมเพลตที่อนุมัติ
Outcome:
- 200
- 403
- 409
- 422
GET /api/plugins
หัวข้อที่มีชื่อว่า “GET /api/plugins”แสดงรายการ installation ทุก installation ที่ยังไม่ถูก revoke บนไซต์ แบบปกปิดข้อมูล: ไม่มี token ไม่มี hash
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - ไม่มี body
- คำตอบ:
{ "data": [<installation>] }—$defs/installation
Outcome:
- 200
- 403
missing_permission
GET /api/plugins/models
หัวข้อที่มีชื่อว่า “GET /api/plugins/models”โมเดลที่ grant ได้ id, ชื่อ และ slug ของทุกโมเดลเนื้อหาบนไซต์ สำหรับหน้าจอ grant GRANT เก็บ id ดังนั้นการเปลี่ยนชื่อยังคงรักษามันไว้ และโมเดลที่ถูกลบจะทำให้ส่วนนั้นของมันไม่มีผล
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - ไม่มี body
- คำตอบ:
{ "data": [{ "id", "name", "slug" }] }
Outcome:
- 200
- 403
missing_permission
GET /api/plugins/catalogue
หัวข้อที่มีชื่อว่า “GET /api/plugins/catalogue”อ่านแคตตาล็อกปลั๊กอิน ดึง URL แคตตาล็อกทุกตัวที่ผู้ดูแลระบบตั้งไว้ใน PLUGIN_CATALOGUE_URLS ภายใต้กฎ URL และการปฏิเสธการเปลี่ยนเส้นทางแบบเดียวกับ manifest ไม่มีอะไรถูกเก็บและไม่มีอะไรได้รับความไว้วางใจ: รายการให้เพียง URL ของ manifest และการติดตั้งจากรายการคือ Review และ Install ตามปกติ ซึ่งดึงและตรวจ manifest อีกครั้ง หน้าแคตตาล็อกคือ { "catalogue_version": 1, "plugins": [<entry>], "next"?: "https://…" } รายการคือ { "id", "name", "manifest_url", "summary"?, "categories"?, "homepage"?, "icon"? } โดยไม่มีคีย์อื่น id ใช้กฎเดียวกับ id ของ manifest name ยาวได้ไม่เกิน 64 ตัวอักษร summary ไม่เกิน 280 categories มี slug ตัวพิมพ์เล็กได้ไม่เกิน 5 ตัว URL ทุกตัวต้องผ่านกฎ URL ของปลั๊กอิน next ต้องอยู่บน origin ของหน้าแรก ขีดจำกัดต่อแคตตาล็อก: 5 หน้า หน้าละ 128 KiB หน้าละ 100 รายการ และรวม 200 รายการ อ่านได้สูงสุด 4 แคตตาล็อก แคตตาล็อกที่ผิดกฎถูกตัดออกทั้งหมดและระบุใน catalogues รายการที่ไม่ถูกต้องถูกข้ามและระบุใน problems เมื่อสองรายการมี id เดียวกัน รายการแรกชนะ: ตามลำดับแคตตาล็อกที่ตั้งค่า แล้วตามลำดับหน้า แล้วตามลำดับรายการ แคตตาล็อกที่ล้มเหลวไม่เปลี่ยนปลั๊กอินที่ติดตั้งแล้วหรือการติดตั้งโดยตรง
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - ไม่มี body
- คำตอบ:
{ "data": { "configured", "entries": [{ "id", "name", "summary", "categories", "manifest_url", "homepage", "icon", "catalogue" }], "catalogues": [{ "catalogue", "origin", "ok", "entries" | "reason" }], "problems": [{ "catalogue", "index", "plugin_id", "reason", "fields" }] } }
Outcome:
- 200 — รวมถึงเมื่อไม่ได้ตั้งค่าแคตตาล็อก (
configured: false) และเมื่อทุกแคตตาล็อกล้มเหลวreasonของแคตตาล็อกคือurl_invalid,url_not_https,url_credentials,url_fragment,url_private_destination,remote_redirect_refused,remote_body_too_large,remote_unreachable,catalogue_unavailable,catalogue_invalid,catalogue_next_refused,catalogue_too_many_pages,catalogue_too_many_entriesหรือtoo_many_cataloguesreasonของปัญหาคือentry_invalidหรือentry_duplicate - 403
missing_permission
GET /api/plugins/actions
หัวข้อที่มีชื่อว่า “GET /api/plugins/actions”action ของเนื้อหาที่จะ render คู่ { id, label } ที่มีขอบเขตซึ่ง installation ที่ active ประกาศไว้ เพื่อให้หน้าจอเนื้อหา render ปุ่มที่ core เป็นเจ้าของได้ ไม่มี markup, ไม่มี script, ไม่มี CSS, ไม่มี URL ของไอคอนใดมาจากปลั๊กอินเลย เมื่อมี instance_id จะแสดงเฉพาะ installation ที่ grant ของโมเดลรวมโมเดลของรายการนั้น และรายการที่ไม่รู้จักจะไม่แสดงอะไรเลย
- ผู้เรียก: สมาชิกใดก็ได้ของไซต์
- ต้องการ: ไม่มีอะไรนอกจากสิทธิ์เข้าถึงไซต์
instance_id(query ที่ไม่บังคับ) — รายการที่ปุ่มเหล่านี้มีไว้สำหรับ ไม่มี body- คำตอบ:
{ "data": [{ "installation_id", "plugin_name", "actions": [{ "id", "label" }] }] }
Outcome:
- 200
GET /api/plugins/cards
หัวข้อที่มีชื่อว่า “GET /api/plugins/cards”การ์ดในแถบข้างที่จะ render การ์ด entry_sidebar หรือ page_sidebar ที่ installation ที่ active ประกาศไว้ใน ui_extensions core วาดการ์ดแต่ละใบเองจาก title และ description: ไม่มี markup, script, CSS, frame หรือ URL ใดมาจากปลั๊กอิน การ์ด launch ผ่าน route launch ด้านล่าง การ์ดของ content action แสดงเฉพาะสำหรับรายการที่โมเดลอยู่ใน grant การ์ดของหน้าจัดการแสดงสำหรับรายการแบบนั้น หรือสำหรับผู้ใช้ที่มี site:plugins รายการที่ไม่รู้จักจะไม่แสดงการ์ดเลย
- ผู้เรียก: สมาชิกใดก็ได้ของไซต์
- ต้องการ: ไม่มีอะไรนอกจากสิทธิ์เข้าถึงไซต์
placement(query) —entry_sidebarหรือpage_sidebarinstance_id(query ที่ไม่บังคับ) — รายการบนหน้าจอ ไม่มี body- คำตอบ:
{ "data": [<plugin_card>] }—$defs/plugin_card
Outcome:
- 200
- 400
invalid_placement
GET /api/plugins/operations
หัวข้อที่มีชื่อว่า “GET /api/plugins/operations”การดำเนินการที่ผู้ใช้นี้เรียกใช้ได้ operations ที่การติดตั้งที่ใช้งานอยู่ประกาศไว้และผู้ใช้นี้เรียกใช้ได้ตอนนี้ ไม่มี instance_id: การดำเนินการระดับไซต์ (ต้องมี site:plugins) และการดำเนินการกับรายการในโมเดลที่ผู้ใช้อ่านได้ มี instance_id: การดำเนินการของรายการนั้น การดำเนินการที่สิทธิ์ขาด requires จะไม่แสดง การดำเนินการ automation และคอลัมน์ในรายการเนื้อหาก็ไม่แสดงเช่นกัน endpoint ไม่ถูกแสดงเลย
- ผู้เรียก: สมาชิกคนใดก็ได้ของไซต์
- ต้องมี: ไม่มีอะไรนอกจากการเข้าถึงไซต์
instance_id(query ไม่บังคับ) — รายการบนหน้าจอ ไม่มี body- ตอบ:
{ "data": [{ installation_id, plugin_id, plugin_name, operation }] }
ผลลัพธ์:
- 200
POST /api/plugins/:id/operations/:operationId/run
หัวข้อที่มีชื่อว่า “POST /api/plugins/:id/operations/:operationId/run”เรียกใช้การดำเนินการ core ตรวจค่ากับข้อมูลเข้าที่ประกาศ บันทึกการเรียกใช้ POST ซองไปยัง endpoint ที่ประกาศ แล้วรอการแลกรหัสและคำตอบ คำตอบที่เสร็จสมบูรณ์ถูกตรวจกับ $defs/operation_result และคอมโพเนนต์ผลลัพธ์ที่ประกาศ และบันทึกการตรวจสอบด้วย digest การส่งซ้ำแบบตรงกันด้วย Idempotency-Key และ body เดิมจะคืนผลลัพธ์แรกพร้อม replayed: true
- ผู้เรียก: ผู้ใช้ที่เห็นการดำเนินการนั้นในรายการ
- ต้องมี: กฎของการดำเนินการเอง:
site:pluginsสำหรับระดับไซต์ สิทธิ์อ่านรายการสำหรับการดำเนินการกับรายการ สิทธิ์แก้ไขสำหรับที่ทำลายข้อมูล - Body —
{ "instance_id"?: string, "input"?: { … } }instance_idจำเป็นสำหรับการดำเนินการกับรายการและถูกปฏิเสธสำหรับระดับไซต์ Idempotency-Key— จำเป็น- ตอบ:
{ "data": { invocation_id, installation_id, plugin_id, plugin_name, operation, instance_id, outcome: "completed", result } }
ผลลัพธ์:
- 400
idempotency_key_required,malformed_body,invalid_request,input_invalid(พร้อมissues),input_too_large - 404
operation_unavailable— ไม่รู้จัก เป็นการดำเนินการautomationเป็นคอลัมน์ในรายการเนื้อหา หรือไม่ได้เสนอให้ผู้ใช้นี้ตอนนี้ - 409
idempotency_key_reused,invocation_in_progress,plugin_unavailable - 422
plugin_refused—refusal: { code, message }ของปลั๊กอินเอง - 502
plugin_unreachable,plugin_response_invalid - 503
audit_unavailable - 504
plugin_timeout
GET /api/plugins/columns
หัวข้อที่มีชื่อว่า “GET /api/plugins/columns”คอลัมน์ในรายการเนื้อหาที่ต้องวาด การดำเนินการ page ที่การติดตั้งที่ใช้งานอยู่ประกาศไว้สำหรับโมเดลหนึ่ง: scope: "page", audience: "column" และชนิด cell core เพิ่มคอลัมน์ที่มีหัวเป็นชื่อการดำเนินการในรายการเนื้อหาของโมเดลนั้น คอลัมน์แสดงเฉพาะเมื่อการติดตั้งใช้งานอยู่ โมเดลอยู่ในสิทธิ์ requires ของมันได้รับสิทธิ์ และผู้ใช้อ่านโมเดลได้ scope และรายการโมเดลของ credential จำกัดมันเช่นเดียวกับส่วนอื่นของ API ปลั๊กอิน
- ผู้เรียก: สมาชิกของไซต์ที่อ่านโมเดลได้
- ต้องมี: ไม่มีอะไรนอกจากการอ่านโมเดล
model_id(query) — จำเป็น ไม่มี body- ตอบ:
{ "data": [{ installation_id, plugin_name, operation, header, cell }] }cellคือtext,badgeหรือlink
ผลลัพธ์:
- 200
- 400
model_id_required
POST /api/plugins/:id/columns/:operationId/cells
หัวข้อที่มีชื่อว่า “POST /api/plugins/:id/columns/:operationId/cells”คำนวณหนึ่งคอลัมน์สำหรับหนึ่งหน้าของแถว core เก็บแถวที่ผู้ใช้อ่านได้ตอนนี้ (ไม่เกิน 50 ในโมเดลที่ระบุ ไม่อยู่ในถังขยะ) และรันการดำเนินการ page ผ่านทรานสปอร์ตการเรียกใช้เดียวด้วยข้อมูลเข้า $defs/column_request: โมเดลและรหัสของแถวเหล่านั้น ไม่มีค่า ปลั๊กอินตอบบล็อก cells หนึ่งบล็อก มีไม่เกินหนึ่งเซลล์ต่อแถวที่ถูกถาม เซลล์ของแถวอื่น แถวซ้ำ ลิงก์ที่ไม่มี url แบบ https url หรือ tone บนชนิดที่ไม่รับ หรือข้อความเกิน 80 ตัวอักษร ทำให้คำตอบทั้งหมดเป็น plugin_response_invalid คอลัมน์เป็นการอ่าน: ไม่สร้างการมอบสิทธิ์ ไม่เก็บคำตอบที่เล่นซ้ำ และไม่เขียนแถวบันทึกการตรวจสอบ
- ผู้เรียก: ผู้ใช้ที่อ่านโมเดลได้
- ต้องมี: ไม่มีอะไรนอกจากการอ่านโมเดล
- Body —
{ "model_id": string, "instance_ids": string[1..50] }ปิด - ตอบ:
{ "data": { installation_id, plugin_name, operation, header, cell, cells: [{ id, text, tone?, url? }] } }cellsว่างเมื่อผู้ใช้อ่านแถวใดไม่ได้เลยหรือปลั๊กอินไม่มีอะไรจะแสดง
ผลลัพธ์:
- 400
malformed_body,invalid_request - 404
operation_unavailable— ไม่รู้จัก ไม่ใช่คอลัมน์ หรือไม่ได้เสนอให้ผู้ใช้นี้ตอนนี้ - 409
plugin_unavailable - 422
plugin_refused - 502
plugin_unreachable,plugin_response_invalid - 504
plugin_timeout
GET /api/plugins/list-actions
หัวข้อที่มีชื่อว่า “GET /api/plugins/list-actions”การทำงานกับแถวที่เลือก การดำเนินการ entry แบบ interactive ที่มี list_action: true ซึ่งการติดตั้งที่ใช้งานอยู่ประกาศไว้สำหรับโมเดลหนึ่ง core เสนอมันกับแถวที่ผู้ใช้เลือกในรายการเนื้อหา อันที่ทำลายข้อมูลแสดงเฉพาะผู้ที่แก้ไขในโมเดลได้ endpoint ไม่ถูกแสดงเลย
- ผู้เรียก: สมาชิกของไซต์ที่อ่านโมเดลได้
- ต้องมี: ไม่มีอะไรนอกจากการอ่านโมเดล
model_id(query) — จำเป็น ไม่มี body- ตอบ:
{ "data": [{ installation_id, plugin_id, plugin_name, operation }] }
ผลลัพธ์:
- 200
- 400
model_id_required
POST /api/plugins/:id/list-actions/:operationId/run
หัวข้อที่มีชื่อว่า “POST /api/plugins/:id/list-actions/:operationId/run”รันการทำงานกับแถวที่เลือก core รันการดำเนินการหนึ่งครั้งต่อแต่ละแถวที่ระบุ ผ่านบริการเดียวกับ Run an operation ดังนั้นแต่ละแถวจึงถูกตรวจกับสิทธิ์ปัจจุบันของผู้ใช้ ตรวจกับข้อมูลเข้าที่ประกาศ บันทึกการตรวจสอบ และมีคำตอบของตัวเอง ไม่เกิน 25 แถวที่ต่างกัน รันครั้งละไม่กี่แถว การปฏิเสธแถวหนึ่งไม่หยุดแถวอื่น คีย์ idempotency ของแต่ละแถวมาจาก Idempotency-Key ของคำขอและรหัสแถว ดังนั้นการลองซ้ำทั้งคำขอจะเล่นซ้ำแถวที่รันไปแล้วและรันที่เหลือ
- ผู้เรียก: ผู้ใช้ที่เห็นการดำเนินการนั้นในรายการ ทีละแถว
- ต้องมี: กฎของการดำเนินการเองสำหรับแต่ละแถว: สิทธิ์อ่านรายการ สิทธิ์แก้ไขสำหรับที่ทำลายข้อมูล
- Body —
{ "instance_ids": string[1..25], "input"?: { … } }ปิดinputเดียวกันใช้กับทุกแถว Idempotency-Key— จำเป็น- ตอบ:
{ "data": { "results": [<item>], "summary": { completed, failed } } }item คือ{ instance_id, ok: true, run }โดยrunคือการรันการดำเนินการของRun an operationหรือ{ instance_id, ok: false, status, reason, error, refusal? }พร้อมเหตุผลที่ route นั้นจะตอบสำหรับแถวนั้น
ผลลัพธ์:
- 200 — ไม่ว่าผลของแต่ละแถวจะเป็นอย่างไร
- 400
idempotency_key_required,malformed_body,invalid_request - 404
operation_unavailable— ไม่รู้จักหรือไม่ใช่การทำงานกับแถว
GET /api/plugins/field-editors
หัวข้อที่มีชื่อว่า “GET /api/plugins/field-editors”ตัวแก้ไขฟิลด์ที่จะ render installation ทุกตัวที่ active หรือถูกปิด พร้อม extension field_editor ที่ manifest ที่เก็บไว้ประกาศ core วาดตัวแก้ไขของปลั๊กอินเฉพาะสำหรับ installation ที่ active และเฉพาะเมื่อฟิลด์ยังเข้ากับมัน มิฉะนั้นฟิลด์ยังเก็บค่าไว้ และ core วาดตัวแก้ไขในตัวของตัวเอง พร้อมบอกชื่อปลั๊กอินและเหตุที่ตัวแก้ไขของมันใช้ไม่ได้ ฟิลด์ของโมเดลระบุตัวแก้ไขใน ui.pluginEditor ({ "plugin": "<plugin id>", "extension": "<extension id>" }) การบันทึกโมเดลที่เพิ่มหรือเปลี่ยนการอ้างอิงนี้จะถูกปฏิเสธ เว้นแต่ installation ที่ active ประกาศตัวแก้ไขนั้น และฟิลด์มีชนิดที่เก็บ กฎ และตัวเลือกของมัน (400 plugin_editor_not_installed, plugin_editor_not_active, plugin_editor_not_found, plugin_editor_type_mismatch, plugin_editor_rules_mismatch, plugin_editor_options_mismatch หรือ plugin_editor_invalid) การอ้างอิงที่ไม่เปลี่ยนยังคงอยู่หลังปลั๊กอินถูกปิดหรือถอนการติดตั้ง
- ผู้เรียก: สมาชิกใดก็ได้ของไซต์
- ต้องการ: ไม่มีอะไรนอกจากสิทธิ์เข้าถึงไซต์
- ไม่มี body
- คำตอบ:
{ "data": [<field_editor_source>] }—$defs/field_editor_source
Outcome:
- 200
GET /api/plugins/rich-blocks
หัวข้อที่มีชื่อว่า “GET /api/plugins/rich-blocks”บล็อก rich text ที่จะเสนอ installation ทุกตัวที่ active หรือถูกปิด ซึ่ง manifest ที่เก็บไว้ประกาศ rich_blocks โดยแต่ละนิยามอยู่ใน namespace <plugin id>/<name> ตัวแก้ไข rich text เสนอบล็อกของ installation ที่ active ในเมนูแทรก วาดฟิลด์ของบล็อกเอง และแสดงพรีวิวจาก tree render ที่ประกาศ บล็อกที่เก็บไว้คงชนิด เวอร์ชัน และค่าเมื่อปลั๊กอินถูกปิดหรือถอนการติดตั้ง ตัวแก้ไขแสดงว่าเก็บไว้แต่ไม่ได้ลงทะเบียน และ renderer ไม่แสดงอะไรสำหรับบล็อกนั้นบนหน้าสาธารณะ การบันทึกเนื้อหาที่เพิ่มหรือเปลี่ยนบล็อกของปลั๊กอินจะถูกปฏิเสธ เว้นแต่ installation ที่ active ประกาศชนิดของบล็อก (422 rich_block_unregistered) รู้จักเวอร์ชัน (rich_block_version_unknown) และรับค่าหลัง migration ที่ประกาศไว้ (rich_block_values_invalid) บล็อกที่ไม่เปลี่ยนถูกเก็บไว้ไม่ว่าอะไรจะลงทะเบียนอยู่
- ผู้เรียก: สมาชิกใดก็ได้ของไซต์
- ต้องการ: ไม่มีอะไรนอกจากสิทธิ์เข้าถึงไซต์
- ไม่มี body
- คำตอบ:
{ "data": [<rich_block_source>] }—$defs/rich_block_source
Outcome:
- 200
GET /api/plugins/calendars
หัวข้อที่มีชื่อว่า “GET /api/plugins/calendars”view บรรณาธิการที่บุคคลนี้เปิดได้ ทุก installation ที่ยังไม่ถูกถอนการติดตั้งและ manifest ที่เก็บไว้ประกาศ manage view (calendar, releases) พร้อม view ที่ประกาศและสถานะสำหรับบุคคลนี้: available (active และบุคคลนั้นอ่านโมเดลใน grant ได้อย่างน้อยหนึ่งโมเดล รวมถึงอ่านได้เฉพาะรายการของตัวเอง), no_readable_models (บุคคลนั้นอ่านโมเดลใน grant ไม่ได้เลยสักโมเดล), disabled หรือ unavailable (ยังไม่ active) รายการว่างหมายความว่าไม่ได้ติดตั้งปลั๊กอินแบบนี้ ไม่แสดงอะไรเกี่ยวกับ grant มากกว่านั้น
- ผู้เรียก: สมาชิกใดก็ได้ของไซต์
- ต้องการ: ไม่มีอะไรนอกจากสิทธิ์เข้าถึงไซต์
- ไม่มี query และไม่มี body
- คำตอบ:
{ "data": [{ "installation_id", "plugin_name", "views", "state" }] }
Outcome:
- 200
POST /api/plugins/review
หัวข้อที่มีชื่อว่า “POST /api/plugins/review”ดึงและตรวจสอบ manifest ดึง URL ของ manifest ตรวจสอบมัน และคืนสิ่งที่มันขอ ไม่มีอะไรถูกเก็บและไม่มี installation เกิดขึ้นหลังจากนั้น นี่คือขั้นตอนตรวจทานที่ทำให้การอนุมัติเป็นไปอย่างมีข้อมูล
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - Body —
{ "manifest_url": "https://…" } - คำตอบ:
{ "data": { "manifest": <manifest>, "protocol_version": 1, "review_digest": "<sha256>" } }
Outcome:
- 200
- 400
malformed_body/ reason ของ manifest —manifest_invalid,protocol_unsupported,manifest_origin_mismatch,manifest_unavailable,url_invalid,url_not_https,url_credentials,url_fragment,url_private_destination,remote_redirect_refused,remote_body_too_large,remote_unreachable - 403
missing_permission
POST /api/plugins
หัวข้อที่มีชื่อว่า “POST /api/plugins”ติดตั้ง ดึงและตรวจสอบ manifest อีกครั้ง บันทึก installation สถานะ pending พร้อม capability และ id ของโมเดลที่อนุมัติ ออก token และส่ง token ดิบพร้อม activation code แบบใช้ครั้งเดียวไปยัง activation_url ของ manifest installation จะกลายเป็น active ก็ต่อเมื่อได้ 2xx จากปลั๊กอินเท่านั้น core เก็บ hash และไม่เคยเก็บ token activation ที่ล้มเหลวจะไม่ทิ้งอะไรไว้ และการติดตั้งปลั๊กอินเดียวกันเป็นครั้งที่สองบนไซต์เดียวกันคือ conflict ไม่ใช่ installation ที่สอง
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - Body —
{ "manifest_url", "activation_code", "capabilities": […], "model_ids": […] }ฟิลด์expected_review_digestที่เลือกส่งได้จะตรึง URL และแมนิเฟสต์จากผลการตรวจ หากเปลี่ยนไป ระบบจะปฏิเสธก่อนส่งโทเคน capability ต้องเป็น subset ของคำขอใน manifestmodel_idsที่ว่างหมายถึงไม่มีสิทธิ์เข้าถึงเนื้อหา ไม่ใช่ทุกโมเดล - คำตอบ:
{ "data": <installation> }, 201
Outcome:
- 201
- 400
malformed_body/invalid_activation_code/invalid_capabilities/invalid_model_ids/ reason ของ manifest - 403
missing_permission - 409
installation_exists/backend_url_unset/activation_superseded/manifest_changed_since_review - 502 พร้อม
reason—activation_refused(คำตอบที่ไม่ใช่ 2xx),url_invalid,url_not_https,url_credentials,url_fragment,url_private_destination,remote_redirect_refused,remote_body_too_large,remote_unreachable— ปลั๊กอินปฏิเสธหรือไม่สามารถติดต่อได้ ไม่มีอะไรถูกติดตั้ง - 503
audit_unavailable
PUT /api/plugins/:id/grant
หัวข้อที่มีชื่อว่า “PUT /api/plugins/:id/grant”เปลี่ยน grant แทนที่ capability และ id ของโมเดล ชุดสิทธิ์ที่กำหนดต้องอยู่ภายในสิ่งที่ manifest ที่ เก็บไว้ ขอ — capability ที่อยู่นอกนั้นจะถูกปฏิเสธ ดังนั้น manifest ที่เปลี่ยนไปไม่สามารถขยาย grant ได้ การลดสิทธิ์มีผลใน request ถัดไปของปลั๊กอิน
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - Body —
{ "capabilities": […], "model_ids": […] } - คำตอบ:
{ "data": <installation> }
Outcome:
- 200
- 400
malformed_body/invalid_capabilities/invalid_model_ids - 403
missing_permission - 404
not_found - 409
installation_state_changed - 503
audit_unavailable
PUT /api/plugins/:id/policies/:policyId
หัวข้อที่มีชื่อว่า “PUT /api/plugins/:id/policies/:policyId”เลือกว่าเมื่อนโยบายเนื้อหาไม่ตอบจะเกิดอะไรขึ้น ตั้งนโยบายที่ประกาศไว้หนึ่งรายการเป็น warn (ค่าเริ่มต้น: หมดเวลา ระบบล่ม หรือคำตอบผิดรูปแบบ จะให้การเขียนผ่านพร้อมคำเตือน) หรือ required (ความล้มเหลวเดียวกันจะปฏิเสธการเขียน) refuse จริงจะปฏิเสธเสมอ expected_mode คือโหมดที่ผู้ดูแลเห็น การเปลี่ยนแปลงอื่นระหว่างนั้น หรือการอัปเกรดที่ยอมรับแล้ว ถือเป็นข้อขัดแย้ง
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - Body —
{ "mode": "required", "expected_mode": "warn" } - คำตอบ:
{ "data": <installation> }
Outcome:
- 200
- 400
malformed_body - 403
missing_permission - 404
not_found/policy_not_found - 409
policy_mode_changedพร้อมmodeปัจจุบัน - 503
audit_unavailable
PUT /api/plugins/:id/hooks/:hookId
หัวข้อที่มีชื่อว่า “PUT /api/plugins/:id/hooks/:hookId”เปิดหรือปิด hook ก่อนการดำเนินการ ตั้ง hook ที่ประกาศไว้หนึ่งรายการเป็น on หรือ off hook ที่ประกาศไว้จะเป็น off จนกว่าผู้ดูแลจะเปิด ขณะเป็น on hook upload_metadata ถูกถามก่อนรับไฟล์ใหม่เข้าคลัง และ comment_moderation ก่อนเก็บความคิดเห็นของผู้เยี่ยมชม hook ที่ตอบไม่ได้จะปฏิเสธการอัปโหลดหรือปล่อยความคิดเห็นให้รอการตรวจ และไม่อนุมัติเด็ดขาด expected_mode คือสถานะที่ผู้ดูแลเห็น การเปลี่ยนแปลงอื่นระหว่างนั้น หรือการอัปเกรดที่ยอมรับแล้ว ถือเป็นข้อขัดแย้ง
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - Body —
{ "mode": "on", "expected_mode": "off" } - คำตอบ:
{ "data": <installation> }
Outcome:
- 200
- 400
malformed_body - 403
missing_permission - 404
not_found/hook_not_found - 409
hook_mode_changedพร้อมmodeปัจจุบัน - 503
audit_unavailable
POST /api/plugins/:id/upgrade
หัวข้อที่มีชื่อว่า “POST /api/plugins/:id/upgrade”ยอมรับ manifest เวอร์ชันใหม่ ดึง URL ของ manifest ที่เก็บไว้อีกครั้งและยอมรับ release ที่ผู้ดูแลเพิ่งตรวจทาน — expected_version ต้องตรงกับสิ่งที่ถูก serve มิฉะนั้นการตรวจทานถือว่าเก่าแล้ว id ของปลั๊กอิน, origin และเวอร์ชัน protocol ที่ยอมรับต้องไม่เปลี่ยน ระบบจะเก็บเฉพาะ capability ที่ได้รับสิทธิ์อยู่แล้วและยังอยู่ในคำขอใหม่ การอัปเกรดไม่เคยขยาย grant release ที่เปลี่ยนเวอร์ชัน protocol ที่ยอมรับไม่สามารถถูกยอมรับได้: ให้ถอนการติดตั้งแล้วติดตั้งใหม่ นโยบายที่ release ใหม่ไม่ได้ประกาศแล้วจะเสียโหมดของตน นโยบายใหม่เริ่มที่ warn
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - Body —
{ "expected_version": "0.2.0" } - คำตอบ:
{ "data": <installation> }
Outcome:
- 200
- 400
malformed_body/ reason ของ manifest - 403
missing_permission - 404
not_found - 409
manifest_identity_changed/protocol_changed/manifest_changed_since_review/installation_state_changed - 503
audit_unavailable
POST /api/plugins/:id/rotate
หัวข้อที่มีชื่อว่า “POST /api/plugins/:id/rotate”Rotate token ต้องใช้รหัสใช้ครั้งเดียวใหม่จากปลั๊กอิน เพราะการ rotate คือการส่งมอบ ไม่ใช่การรีเซ็ต core ออก token ส่งไปยัง activation origin ที่ถูก pin และหลังจากนั้นจึงสลับ hash หากปลั๊กอินปฏิเสธ token เก่ายังใช้งานได้ hash ก่อนหน้ายังใช้ได้ไม่เกิน 10 นาที และ request แรกที่แนบ token ใหม่ จะยุติช่วงซ้อนทับนั้นทันที: ตั้งแต่นั้น token เก่าจะตอบ 401 plugin_unauthorized ปลั๊กอินที่มีหลาย worker ต้องสลับทั้งหมดพร้อมกัน หรือให้ worker อ่าน token ที่เก็บไว้ซ้ำหนึ่งครั้งเมื่อได้ 401 ทันทีหลังการ rotate
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - Body —
{ "activation_code": "…" } - คำตอบ:
{ "data": { "rotated": true } }
Outcome:
- 200
- 400
invalid_activation_code(รวมถึง body ที่ไม่ใช่ JSON object ด้วย) - 403
missing_permission - 404
not_found - 409
installation_not_active/backend_url_unset/installation_state_changed - 502 พร้อม
reason—activation_refused(คำตอบที่ไม่ใช่ 2xx),url_invalid,url_not_https,url_credentials,url_fragment,url_private_destination,remote_redirect_refused,remote_body_too_large,remote_unreachable— และ token เก่า ยังใช้งานได้ - 503
audit_unavailable
POST /api/plugins/:id/disable
หัวข้อที่มีชื่อว่า “POST /api/plugins/:id/disable”Disable เก็บการตั้งค่าและ audit trail ไว้ และหยุด plugin API ทันที: ทุก request ตอบ plugin_unauthorized ก่อนการเข้าถึง tenant ใด ๆ การ์ดของมันหายไป และฟิลด์ที่ระบุตัวแก้ไขฟิลด์ของมันยังเก็บค่าไว้และถูกวาดด้วยตัวแก้ไขในตัว
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - ไม่มี body
- คำตอบ:
{ "data": { "id", "state": "disabled" } }
Outcome:
- 200
- 403
missing_permission - 404
not_found - 409
installation_state_changed - 503
audit_unavailable
POST /api/plugins/:id/enable
หัวข้อที่มีชื่อว่า “POST /api/plugins/:id/enable”Enable คืน installation ที่ถูก disable กลับเป็น active ด้วย token เดิมและ grant เดิม
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - ไม่มี body
- คำตอบ:
{ "data": { "id", "state": "active" } }
Outcome:
- 200
- 403
missing_permission - 404
not_found - 409
installation_state_changed - 503
audit_unavailable
DELETE /api/plugins/:id
หัวข้อที่มีชื่อว่า “DELETE /api/plugins/:id”ถอนการติดตั้ง revoke ก่อน: state กลายเป็น revoked, hash ทั้งสองถูกทิ้ง และ token จะไม่กลับมาใช้ได้อีก การระบุที่มาใน audit ยังคงอยู่ เพราะ workflow event เก็บ snapshot ของ installation แทนที่จะเป็น foreign key Dee Wan ไม่ อ้างว่าการนี้ลบสิ่งใดที่ปลั๊กอินถืออยู่ — การลบฝั่ง remote เป็น action ของปลั๊กอินเอง การถอนการติดตั้งทำได้แม้ฟิลด์ของโมเดลยังระบุตัวแก้ไขฟิลด์ของมัน: ฟิลด์เหล่านั้นยังเก็บค่าและกฎไว้และถูกวาดด้วยตัวแก้ไขในตัว
- ผู้เรียก: ผู้ใช้ที่มี
site:plugins - ต้องการ:
site:plugins - ไม่มี body
- คำตอบ:
{ "data": { "id", "state": "revoked" } }
Outcome:
- 200
- 403
missing_permission - 404
not_found - 409
installation_state_changed - 503
audit_unavailable
POST /api/plugins/:id/launch
หัวข้อที่มีชื่อว่า “POST /api/plugins/:id/launch”เปิดปลั๊กอินแบบ delegate ออกรหัสใช้ครั้งเดียว มีอายุ 60 วินาที เก็บแบบ hash ผูกกับ installation, ไซต์, ผู้ใช้, action และ instance (ไม่บังคับ) และคืน management_url พร้อมรหัสนั้น response มี Referrer-Policy: no-referrer และ Cache-Control: no-store action ต้องเป็น manage โดยไม่มี instance หรือเป็น id ของ content_actions จาก manifest ที่เก็บไว้พร้อม instance หนึ่งตัว สำหรับ action ของเนื้อหา โมเดลของรายการต้องอยู่ใน grant ของ installation launch แบบ manage อาจระบุ view จาก manage_views ของ manifest ที่เก็บไว้ จากนั้น URL จะมี dee_wan_view ด้วย ซึ่งเป็นคำใบ้หน้าปลายทางที่ไม่ได้ให้สิทธิ์ใดๆ launch ที่มี view เป็นงานบรรณาธิการ: ไม่ต้องมี site:plugins ต้องมีเพียงโมเดลหนึ่งใน grant ที่บุคคลนั้นอ่านได้ ทุกรายการหรือเฉพาะรายการของตัวเอง launch แบบ manage ธรรมดาเป็นการดูแลปลั๊กอินและต้องมี site:plugins delegation บันทึก model_ids: โมเดลใน grant ที่บุคคลนั้นอ่านได้ (สำหรับ action ของเนื้อหา คือโมเดลของรายการนั้น) จำกัดตามโมเดลของ credential ของ management เมื่อ credential นั้นเป็นผู้กระทำ launch ที่ credential ของ management สร้างยังบันทึกเพดาน capability: capability ของ installation ที่ scopes ของ credential อนุญาต คำสั่งทุกครั้งหลังจากนั้นผ่าน delegation นี้ที่อยู่นอกเพดานจะถูกปฏิเสธด้วย capability_refused cookie ของ session Dee Wan ไม่เคยออกจาก Dee Wan
การเปิดมุมมอง manage ที่ประกาศไว้ส่ง entry_context: { instance_id, locale? } ได้ ระบบตรวจสิทธิ์อ่านปัจจุบัน สิทธิ์ของภาษา และขอบเขตที่อนุญาตของการติดตั้งและโมเดล ก่อนเพิ่ม dee_wan_entry และ dee_wan_locale เมื่อระบุภาษา ข้อมูลนี้เป็นเพียงคำแนะนำหน้าปลายทาง ไม่ให้สิทธิ์เพิ่ม การมอบสิทธิ์ของมุมมองยังไม่ผูกกับรายการใดรายการหนึ่ง และปลั๊กอินต้องอ่านรายการนั้นใหม่ด้วยสิทธิ์ปัจจุบัน
- ผู้เรียก: สมาชิกของไซต์สำหรับ content action หรือ view ของ
managesite:pluginsสำหรับmanageธรรมดา - ต้องการ: สิทธิ์อ่านรายการที่ระบุ สำหรับ content action และโมเดลใน grant ที่อ่านได้หนึ่งโมเดล สำหรับ view
- Body —
{ "action": "manage" },{ "action": "manage", "view": "calendar" }(หรือ"releases") หรือ{ "action": "<action id>", "instance_id": "…" } - มุมมองที่ประกาศไว้เพิ่ม
"entry_context": { "instance_id": "…", "locale": "en" }ได้ โดยไม่จำเป็นต้องระบุlocale - คำตอบ:
{ "data": { "url": "https://…?dee_wan_launch=…" } }—$defs/launch
Outcome:
- 200
- 400
malformed_body/invalid_launch_action/invalid_entry_context - 403
missing_permission(สำหรับmanageธรรมดา) /no_readable_models(launch ที่มี view และบุคคลนั้นอ่านโมเดลใน grant ไม่ได้เลยสักโมเดล) /model_denied/not_owner(บุคคลนั้นอ่านรายการไม่ได้) /model_not_granted(โมเดลของรายการอยู่นอก grant) - 404
not_found— ไม่มี installation นั้น หรือไม่มีรายการนั้น - 409
installation_not_active
ตัวแก้ไขฟิลด์แบบมีโครงสร้าง
หัวข้อที่มีชื่อว่า “ตัวแก้ไขฟิลด์แบบมีโครงสร้าง”ส่วนขยาย field_editor ที่มี control: "group" วาดฟิลด์ JSON หนึ่งฟิลด์เป็นสมาชิกที่มีป้ายชื่อไม่เกิน 8 ตัว: text (max_length ไม่เกิน 500), number (min, max, integer), boolean และ select (ตัวเลือกไม่เกิน 12) คีย์ของสมาชิกไม่ซ้ำ ค่าที่เก็บยังเป็นอ็อบเจ็กต์ JSON หนึ่งตัวไม่เกิน 8192 ไบต์ การเลือกตัวแก้ไขในตัวสร้างโมเดลจะเขียนสคีมาแบบปิดของมันลงในฟิลด์ (config.schema พร้อม validationType: "object") และการบันทึกปกติตรวจค่าที่ส่งมาและโครงสร้าง โดยปฏิเสธค่านอกขอบเขตหรือตัวเลือก คีย์ที่ไม่ใช่สมาชิก และค่าที่ไม่ใช่อ็อบเจ็กต์ โหมดฉบับร่างอนุญาตให้ยังไม่กรอกสมาชิกบังคับได้ แต่การบันทึกแบบเข้มงวดและการเผยแพร่ทุกครั้งต้องกรอกให้ครบ สคีมายังอยู่ในฟิลด์เมื่อปลั๊กอินถูกปิดหรือถอนการติดตั้ง ค่าที่เก็บจึงยังใช้ได้ และตัวแก้ไข JSON ในตัววาดค่าเหล่านั้น
การแก้ไขเนื้อหาและการเชื่อมต่อ
หัวข้อที่มีชื่อว่า “การแก้ไขเนื้อหาและการเชื่อมต่อ”การอ่านข้อมูลสรุปเดิมยังทำงาน เพิ่ม delegation_id ใน GET /content/:instanceId เพื่อรับ
saved: { id, version_number, data } จำกัดข้อมูลตามสิทธิ์โมเดล ฟิลด์ ภาษา และเจ้าของปัจจุบัน
ส่วน data เก็บค่าของ snapshot มาตรฐาน ความสัมพันธ์ และสื่อ
ไม่มีการมอบสิทธิ์: ได้ข้อมูลสรุปเท่านั้น
GET /content/:instanceId/versions?delegation_id=…&limit=50&cursor=… แสดงเวอร์ชันที่ยังเก็บอยู่
GET /content/:instanceId/versions/:versionId?delegation_id=… อ่าน snapshot ตามสิทธิ์
การอ่านประวัติตรวจความเป็นเจ้าของรายการหลัก เวอร์ชันที่ถูกลบตามระยะเก็บรักษาจะตอบ content_not_found
POST /content สร้างรายการผ่าน lifecycle ต้องมี content:create, การมอบสิทธิ์ manage และ
Idempotency-Key ส่ง delegation_id, model_id, locales ตัวเลือก: primary_lang, slugs,
unset_fields, relations, locale_relations, media, seo, label ใช้ unset_fields ระบุฟิลด์แยกตามภาษาที่ต้องการลบค่าที่เขียนทับ ฟิลด์ต้องแปลได้ ไม่บังคับกรอก และเปิดใช้ค่าจากภาษาอื่นเมื่อไม่มีคำแปล ห้ามกำหนดค่าและลบค่าในฟิลด์เดียวกันพร้อมกัน ใช้รูปแบบเดียวกับ management API
วงจรเนื้อหาตรวจสิทธิ์สร้าง โมเดล ฟิลด์ ภาษา และเป้าหมายที่อ้างถึงทุกรายการ และตอบ content_saved
PUT /content/:instanceId รับ relations, locale_relations, media เพิ่มจาก fields เดิม
ต้องระบุ expected_version_id และเว้น fields ว่างได้เมื่อเปลี่ยนข้อมูลอ้างอิง
ยังคงรับ locale และ delegation_id เดิม รูปแบบความสัมพันธ์และสื่อเหมือนการเขียนผ่าน API การจัดการ และใช้การตรวจวงจรเนื้อหา การตรวจเวอร์ชันก่อนเขียน และ idempotency ชุดเดียวกัน
DELETE /content/:instanceId ย้ายทั้งรายการไปถังขยะ ส่ง delegation_id และ expected_version_id
ต้องมี Idempotency-Key, content:delete และสิทธิ์ลบของผู้ใช้ ถอนการเผยแพร่รายการที่ออนไลน์ก่อน
ตอบ content_deleted การลองซ้ำคืนผลเดิม
การตรวจเวอร์ชันในการเขียนแบบอะตอมมิกป้องกันข้อมูลสูญหายจากการแก้ไขพร้อมกัน
GET /media/:mediaId?delegation_id=… อ่านข้อมูลไฟล์ /bytes อ่านไบต์จากผู้ให้บริการ
ต้องมี media:read และสิทธิ์ media-library read ของผู้ใช้ แยกตามไซต์ รวมไฟล์ส่วนตัวและห้าม cache
คำตอบที่มีไบต์ของไฟล์ส่วนตัวไม่ให้แคช และกำหนดวิธีเปิดหรือดาวน์โหลดไฟล์อย่างปลอดภัย
ไฟล์อ้างอิงภายนอกไม่มีไบต์ในระบบ PUT /media/:mediaId ส่ง {delegation_id,metadata},
Idempotency-Key ต้องมี media:update รองรับ alt_texts, default_focal, loading, fetch_priority
ตอบ media_updated และ {id}
รูปแบบเมทาดาทาเหมือน API การจัดการ และบริการสื่อร่วมจะตรวจการจัดเฟรมด้วย
อินเทอร์เฟซปลั๊กอินแบบฝัง
หัวข้อที่มีชื่อว่า “อินเทอร์เฟซปลั๊กอินแบบฝัง”การ์ดและตัวแก้ไขฟิลด์ประกาศ frame: {url,origin,operations?} ได้ origin ต้องตรงกับ origin ของ URL ของเฟรมและ origin ของปลั๊กอินทุกตัวอักษร การดำเนินการต้องเป็นรายการที่ manifest เดียวกันประกาศไว้
ผู้ดูแลตรวจสอบก่อนยอมรับ Iframe ใช้ credentialless, sandbox="allow-scripts" และ no-referrer
ไม่มี cookies ผู้ดูแลหรือ token เมื่อโหลด host ส่ง dee-wan:connect, protocol 1, value, disabled
พร้อม MessagePort โฮสต์ส่ง {type:"value",value,disabled} ปัจจุบันกลับหลังอัปเดต และจำกัดความสูงที่เฟรมขอ ลูกใช้ port เท่านั้น ส่ง {type:"ready"}, {type:"change",value}, {type:"resize",height} หรือ
{type:"operation",id,operation,input} ได้ Host ตรวจสิทธิ์และคำประกาศ เรียก operation เดิม ตอบ {type:"result",id,result}
id ซ้ำคืนผลเดิม การแก้ไขฟิลด์ผ่านการบันทึกปกติ สิทธิ์ใหม่หลังอัปเกรดยังไม่ได้รับอนุญาต
ไม่มี endpoint สำหรับ fetch ตามอำเภอใจ โทเค็นการติดตั้ง หรือรหัส launch ถูกส่งเข้าเฟรม
บล็อกข้อมูลแบบ rich
หัวข้อที่มีชื่อว่า “บล็อกข้อมูลแบบ rich”relation ระบุ models และ multiple ได้ group ระบุ fields, repeatable, max_items ได้
ซ้อนกลุ่มได้สามระดับ ไม่เกินห้าสิบรายการ ใช้ฟิลด์แบบเดิมและตัวเลือกความสัมพันธ์
Lifecycle ตรวจไซต์ โมเดล และสิทธิ์อ่านเป้าหมาย โครงสร้างการเรนเดอร์ใช้ {group,children} หรือ {each,children} เพื่อกำหนดขอบเขตการเชื่อมโยงข้อมูลของส่วนลูก
สื่อระดับบนและภายในกลุ่มใช้ pin เดิม ย่อหน้าและหัวข้อรองรับ left, center, right, justify
การจัดแนวเก็บด้วย data-align และสไตล์ text-align แบบมาตรฐาน
ใช้สัญญาเดียวกันตั้งแต่ตัวแก้ไขจนถึงหน้าเว็บ
snippet เก็บบล็อกข้อความจัดรูปแบบชนิด snippet โดยมี html/css/javascript/title ส่วน HTML มาตรฐานเก็บ JSON ใน figure ที่ยังไม่ทำงาน พรีวิวในหน้าผู้ดูแลและตัวเรนเดอร์ที่รองรับใช้ endpoint คงที่เฉพาะสำหรับเฟรม และส่งข้อมูลผ่าน MessageChannel ในรูปแบบเดียวกัน ตัวเชื่อมในเอกสารแม่ของหน้าสาธารณะได้รับอนุญาตด้วยแฮช CSP ของเฟรมบังคับให้ทำงานใน sandbox ที่มี origin แบบ opaque โค้ดของผู้ให้บริการจึงอยู่ภายในเฟรม ทั้งสองใช้ข้อมูลเอกสารเดียวกันแบบ credentialless โดยไม่มีสิทธิ์ same-origin สคริปต์ ฟอร์ม และ popup ทำงานภายในเฟรมเท่านั้น ผู้ให้บริการเป็นผู้จัดการข้อมูลการจองหรือฟอร์มที่ส่ง ห้ามเก็บข้อมูลรับรองของผู้ให้บริการในเนื้อหา snippet
ผลลัพธ์ rich relation ที่แก้แล้ว
หัวข้อที่มีชื่อว่า “ผลลัพธ์ rich relation ที่แก้แล้ว”ข้อมูลที่บันทึกเก็บ ID ผลลัพธ์สาธารณะแทนเป้าหมายที่อ่านได้ด้วยออบเจ็กต์สำหรับอ่านที่มีขอบเขต:
reference: true, instance_id, title, url ปัจจุบัน และ properties เฉพาะฟิลด์ scalar
ที่เปิดเผยและถูกระบุด้วย property เช่น { field: "target", property: "address" }
ส่วน { field: "target" } แสดงชื่อ ลิงก์ใช้ที่อยู่ Page/Blog/managed route ที่เผยแพร่จากตัวแก้ร่วม
หรือฟิลด์ url สาธารณะ หากไม่มีที่อยู่จะเป็นข้อความ เป้าหมายที่ซ่อนและฟิลด์ส่วนตัวถูกตัดออก
การบันทึกยังรับเฉพาะ ID โดยไม่ยอมรับชื่อและ URL ที่ผู้เรียกส่งมาเป็นสิทธิ์
Schema ที่เครื่องอ่านได้
หัวข้อที่มีชื่อว่า “Schema ที่เครื่องอ่านได้”schemas/manifest-v1.schema.json— manifest ที่สร้างจากออบเจกต์ ที่ core ใช้ตรวจสอบทุก manifest ที่ดึงมาschemas/protocol-v1.schema.json— request, response, body ของการส่งมอบตอน activation, outcome, ขีดจำกัด และรูปแบบของ secret ที่สร้างจากนิยาม ชุดเดียวกัน shape ของ request เป็นแบบปิด shape ของ response อนุญาตให้มี property เพิ่มเติม เพราะ client ต้องเพิกเฉยต่อ key ใน response ที่ไม่รู้จัก
JSON Schema ไม่ใช่ตัวตรวจความหมายทั้งหมด ต้องเปิดการตรวจ format โดย URL ใช้ uri และ URL จัดการใช้ uri-template URL ของ manifest, base, activation และ management หลังแทนค่าต้องมี origin เดียวกันและผ่านนโยบาย HTTPS/ปลายทางส่วนตัว ยกเว้นเฉพาะ origin สำหรับพัฒนาที่ระบุอย่างเจาะจง การตรวจนี้ไม่ได้ resolve DNS capability ต้องไม่ซ้ำและ id ของ content action ต้องไม่ซ้ำด้วย id ของ ui_extensions ต้องไม่ซ้ำและไม่อยู่ใน reserved_ids และการ์ด launch ได้เฉพาะ id ใน content_actions หรือรายการใน manage_views ที่ manifest เดียวกันประกาศ ต้องมี protocol version ที่รองรับอย่างน้อยหนึ่งค่า grant ที่อนุมัติต้องไม่เกินที่ manifest ขอและโมเดลของไซต์นี้ kind ของ transition กำหนด version pin ที่ต้องมีเพียงตัวเดียว ส่วน status/code/retry ต้องตรงกันหลังตรวจโครงสร้าง
ยังไม่เปิดตัว (pre-MVP) และยังไม่มีเวอร์ชันเสถียร
คอมมิตซอร์สโค้ด: e207e63239a627fbd2ae9c414ef7c6eb19fcfe5a (มีการแก้ไขที่ยังไม่คอมมิต)
วันที่สร้างเอกสาร (UTC): 2026-10-21T09:28:24.214Z
คอมมิตสำหรับอัปเกรด: ระบุไม่ได้: มีการแก้ไขที่ยังไม่คอมมิต. บันทึกการเปลี่ยนแปลง