Webhook

Webhook adalah konfigurasi yang secara otomatis menjalankan tindakan yang telah ditentukan ketika terjadi sesuatu di Space (misalnya, sebuah Content dibuat atau dipublikasikan). Tindakannya adalah salah satu dari dua hal: ia mengirim permintaan HTTP ke URL eksternal (url), atau menjalankan sebuah Script di dalam Space (script). Digunakan untuk integrasi sistem eksternal atau otomatisasi. Misalnya, Anda dapat mengonfigurasinya untuk memanggil server notifikasi internal setiap kali sebuah Content produk dipublikasikan, atau untuk menjalankan pekerjaan lanjutan dengan Script yang telah ditentukan.

Anda menentukan tepat satu dari url dan script. Menentukan keduanya, atau mengosongkan keduanya, akan ditolak. Webhook adalah sumber daya turunan dari Space di CMA, dan jalurnya berbasis pada /spaces/{spaceId}/webhooks.

Struktur sumber daya

Berikut adalah respons pengambilan tunggal dari Webhook "Notifikasi perubahan produk". Bersama dengan sys (properti sistem), ia memiliki field konfigurasi seperti tujuan pengiriman, event yang dilanggan, dan kondisi pemicu.

{
  "sys": {
    "id": "3trmXRM3RqbgSnifyg7PWhk01Examp",
    "type": "Webhook",
    "space": { "sys": { "id": "HnQ32YiH", "type": "Refer", "targetType": "Space" } },
    "createdBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
    "createdAt": "2026-06-18T11:30:00.000Z",
    "updatedBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
    "updatedAt": "2026-06-18T11:30:00.000Z",
    "version": 1
  },
  "name": "Notifikasi perubahan produk",
  "filters": [
    { "doc": "sys.contentType.sys.id", "op": "EQ", "value": "3trmXRLdJF4GBlAjtcuoZ7Pnxj8dlA" }
  ],
  "headers": [
    { "key": "X-Source", "value": "weegloo", "secret": false }
  ],
  "httpBasicUsername": "dailywear",
  "topics": ["Content.Create", "Content.Publish"],
  "transformation": { "method": "POST", "contentType": "application/json", "includeBody": true },
  "url": "https://api.dailywear.example/webhooks/products",
  "activate": true,
  "runAs": "HookOwner"
}

Kunci utama:

  • sys.id: Pengenal unik Webhook. Dimasukkan ke dalam {webhookId} pada jalur pengambilan tunggal, perubahan, dan penghapusan.
  • url: URL tujuan eksternal yang dipanggil ketika event terjadi. Tentukan tepat satu di antara ini dan script.
  • script: Referensi ke Script yang dijalankan alih-alih panggilan eksternal. Tentukan tepat satu di antara ini dan url. Tidak ada pada contoh di atas. Dijelaskan di url dan script (pilih salah satu) di bawah.
  • runAs: Identitas pengguna yang digunakan untuk menjalankan script. Dijelaskan di runAs di bawah.
  • topics: Array yang menentukan event mana yang akan dilanggan. Formatnya dijelaskan di topics di bawah.
  • filters: Kondisi yang benar-benar memicu di antara event yang dilanggan. Dijelaskan di filters di bawah.
  • transformation: Konfigurasi yang mengubah bentuk permintaan yang keluar ke url (metode, body, dll.). Dijelaskan di transformation di bawah.

Properti sistem (sys)

Setiap Webhook menyimpan properti sistem umum dalam objek sys. space, createdBy, dan updatedBy dimasukkan dalam bentuk Refer ({ "sys": { "id", "type": "Refer", "targetType" } }).

PropertiTipeDeskripsi
idstringPengenal unik sumber daya.
typestringJenis sumber daya. Webhook selalu "Webhook".
spaceRefer<Space>Space tempat Webhook ini berada.
createdByRefer<User>Pengguna yang membuat.
createdAtstring (date-time)Waktu pembuatan.
updatedByRefer<User>Pengguna yang terakhir mengubah.
updatedAtstring (date-time)Waktu perubahan terakhir.
versioninteger (≥1)Versi sumber daya. Bertambah 1 setiap kali diubah.

Webhook adalah sumber daya konfigurasi, sehingga tidak memiliki konsep publikasi. Berbeda dengan Content atau Content Type, ia tidak memiliki properti status publikasi seperti publish, archive, atau status, dan hanya memiliki version untuk pelacakan perubahan. Menghidupkan dan mematikan dikendalikan bukan oleh publikasi melainkan oleh field body activate.

Properti body

Body Webhook (nilai konfigurasi yang dikirim saat pembuatan dan perubahan, serta yang dikembalikan dalam respons) terdiri dari field berikut.

FieldTipeWajibDeskripsi
namestring (1~64)Nama Webhook.
urlstring (url)URL tujuan eksternal yang dipanggil ketika event terjadi. Tepat satu di antara ini dan script. Lihat url dan script (pilih salah satu) di bawah.
scriptRefer<Script>Referensi ke Script yang dijalankan alih-alih panggilan eksternal. Tepat satu di antara ini dan url. Lihat url dan script (pilih salah satu) di bawah.
runAsWebhookRunAsIdentitas pengguna yang digunakan untuk menjalankan script. HookOwner (default) atau EventUser. Lihat runAs di bawah.
activatebooleanStatus aktif. Jika false, tidak ada yang dijalankan meskipun event terjadi.
topicsstring[]Array event yang dilanggan. Lihat topics di bawah.
filtersFilter[]Array kondisi pemicu. Jika dikosongkan, semua event yang dilanggan akan memicu. Lihat filters di bawah.
headersWebhookHeader[] (0~30)Array header HTTP yang disertakan pada panggilan url.
httpBasicUsernamestring (1~32)Nama pengguna autentikasi HTTP Basic untuk panggilan url.
httpBasicPasswordstring (1~32)Kata sandi autentikasi HTTP Basic untuk panggilan url. Hanya untuk penulisan. Tidak muncul pada respons.
transformationTransformationMenyesuaikan permintaan yang keluar ke url. Lihat transformation di bawah.

url dan script yang ditandai △ ditentukan tepat satu saja. Menentukan keduanya, atau mengosongkan keduanya, ditolak.

Setiap item pada headers terdiri dari key (wajib), value (wajib), dan secret (opsional, boolean). Jika Anda menyetel secret menjadi true, nilainya tersimpan dalam keadaan disamarkan pada catatan pengiriman (lihat WebhookLog di bawah). Namun jika Anda mengambil Webhook ini, nilainya keluar apa adanya. Yang dihilangkan dari respons hanyalah httpBasicPassword, jadi anggaplah nilai yang Anda letakkan pada header secret terlihat oleh peran yang dapat membaca Webhook ini, dan persempit peran itu.

topics

Setiap item pada topics berformat {resource}.{action}. Contoh: Content.Create, Content.Publish, Media.Create.

Action adalah salah satu dari berikut, atau * yang berarti semua action dari sumber daya tersebut (contoh: Content.*).

ActionArti
AllSemua action.
CreatePembuatan.
ReadPengambilan.
EditPenyuntingan.
SavePenyimpanan (perubahan). Event perubahan adalah Save. Bukan Update.
DeletePenghapusan.
PublishPublikasi.
UnpublishPembatalan publikasi.
ArchivePengarsipan.
UnarchivePembatalan pengarsipan.

filters

filters adalah array yang mempersempit kondisi yang benar-benar memicu Webhook di antara topics yang dilanggan. Setiap filter berbentuk sebagai berikut.

{ "doc": "sys.contentType.sys.id", "op": "EQ", "value": "3trmXRLdJF4GBlAjtcuoZ7Pnxj8dlA" }
  • doc: Jalur field yang dibandingkan. Salah satu dari sys.id, sys.contentType.sys.id, sys.createdBy.sys.id, atau sys.updatedBy.sys.id.
  • op: Operator perbandingan. Salah satu dari EQ, NE, IN, NOT_IN, REGEX, atau NOT_REGEX.
  • value: Nilai pembanding. Berikan string untuk EQ, NE, REGEX, NOT_REGEX, dan array string untuk IN, NOT_IN.

Jika Anda menetapkan beberapa filter, semuanya harus terpenuhi agar memicu (AND). Jika filters dikosongkan, semua event dari topics yang dilanggan akan memicu.

transformation

transformation mengubah bentuk permintaan HTTP yang keluar ke url (tidak berlaku untuk Webhook yang menggunakan script). Jika tidak ditentukan, seluruh payload sumber daya dikirim apa adanya dengan POST default.

KunciTipeDeskripsi
methodstringMetode HTTP. Salah satu dari GET, POST, PUT, DELETE, PATCH.
contentTypestringContent-Type dari body permintaan. Body diserialisasi dalam format ini (di bawah).
bodyobjectObjek yang menyusun body yang dikirim dengan template JSON Pointer.
includeBodybooleanApakah body sumber daya pemicu turut dikirim.

Dalam format apa body dikirim

contentType menentukan format serialisasi body. Perbandingan mengabaikan huruf besar-kecil dan parameter seperti ;charset=…, serta hanya melihat bagian awalnya. Jika tidak ditentukan atau nilainya kosong, body dikirim sebagai application/json. Jika includeBody bernilai false atau method adalah GET, body tidak dikirim, dan dalam kasus itu Content-Type juga tidak disertakan.

Body yang dikirim Webhook selalu berupa objek. Template body adalah sebuah objek, dan jika Anda tidak menetapkan template, seluruh sumber daya yang terpicu dikirim apa adanya.

contentType yang dideklarasikanContent-Type yang benar-benar keluarBody yang keluar
(tidak ada)application/jsonJSON
application/jsonNilai deklarasi apa adanyaJSON
application/x-www-form-urlencodedNilai deklarasi apa adanyaproduct[sku]=TUMBLER-500&product[price]=24000
text/plainapplication/jsonJSON
Selain itu (text/xml dan sebagainya)Nilai deklarasi apa adanyaJSON

text/plain tidak dapat memuat objek, sehingga body dikirim setelah formatnya dikoreksi menjadi format yang dapat memuatnya. Header tidak pernah menyatakan hal yang berbeda dari body yang sebenarnya. Jika tujuan harus menerima body sebagai teks, contentType tidak menyelesaikannya, jadi periksa kontrak di sisi penerima.

form-urlencoded menguraikan objek menjadi kunci bertanda kurung siku dan array menjadi indeks.

BodyKunci dan nilai hasil penguraian
{ "product": { "sku": "TUMBLER-500", "price": 24000 } }product[sku]=TUMBLER-500&product[price]=24000
{ "tags": ["kitchen", "insulated"] }tags[0]=kitchen&tags[1]=insulated
{ "items": [{ "sku": "TUMBLER-500" }] }items[0][sku]=TUMBLER-500
{ "memo": null }memo=

Kunci dan nilai dikirim dengan penyandian persen dalam UTF-8. Tabel di atas menampilkannya dalam bentuk terdekode agar struktur kuncinya terlihat. Meskipun sebuah nilai memuat & atau +, nilai itu tidak disalahartikan sebagai pemisah pasangan atau spasi, dan diteruskan apa adanya.

Menguraikan struktur bersarang menjadi kunci bertanda kurung siku adalah konvensi yang banyak dipakai, bukan spesifikasi dari format itu sendiri. Periksa apakah sisi penerima memulihkan product[sku] menjadi objek bersarang, dan jika tidak, susunlah template body dengan kunci yang rata.

Berikut adalah contoh transformation yang mengirim formulir.

"transformation": {
  "method": "POST",
  "contentType": "application/x-www-form-urlencoded",
  "includeBody": true,
  "body": {
    "sku": "{ /payload/fields/sku/ko-KR }",
    "price": "{ /payload/fields/price/ko-KR }"
  }
}

Ketika sebuah Content dengan sku bernilai TUMBLER-500 dan price bernilai 24000 memicunya, body keluar sebagai sku=TUMBLER-500&price=24000.

url dan script (pilih salah satu)

Ketika Webhook terpicu, ia melakukan salah satu dari dua hal. Jika Anda menentukan url, ia mengirim permintaan HTTP ke URL eksternal tersebut (bentuk permintaan ditetapkan oleh transformation, headers, dan httpBasic*). Jika Anda menentukan script, ia tidak keluar ke eksternal melainkan menjalankan satu Script di dalam Space.

  • url: URL tujuan eksternal (http/https). Tujuan yang diblokir seperti jaringan privat atau loopback ditolak.
  • script: Refer ke Script yang akan dijalankan.

Anda harus menentukan tepat satu dari keduanya. Menentukan keduanya, atau mengosongkan keduanya, akan ditolak, dan kode yang dikembalikan berbeda untuk setiap jalur (lihat Error).

"script": { "sys": { "id": "3trmXRMZcTAjDnphewjj1AaxYcaxlK", "type": "Refer", "targetType": "Script" } }

Ketika terpicu, Script dijalankan dengan izin yang didelegasikan, dan izin sumber daya per statement tidak diperiksa ulang saat runtime. Apa yang diizinkan sudah diperiksa saat Script disusun. Untuk model eksekusi dan izin selengkapnya, lihat Semantik eksekusi, batasan, dan keamanan Script.

runAs

runAs menetapkan identitas pengguna yang digunakan untuk menjalankan script. Identitas ini menjadi createdBy/updatedBy dari sumber daya apa pun yang dibuat atau diubah selama eksekusi, dan filter createdBy: ":self" di dalam Script juga diselesaikan berdasarkan identitas ini. Ini hanya atribusi, bukan batas izin. Apa yang dapat dilakukannya ditentukan oleh pemeriksaan izin yang dilakukan saat Script disusun.

NilaiIdentitas eksekusi
HookOwnerPengguna yang membuat Webhook (sys.createdBy). Nilai default.
EventUserPengguna yang menyebabkan event (perubahan) tersebut, yaitu sys.updatedBy dari sumber daya yang terpicu.

Untuk Webhook yang hanya menggunakan url, runAs diabaikan. Jika tidak ditentukan, nilainya HookOwner.

WebhookLog

Setiap kali Webhook mencoba satu pengiriman, satu catatan tersimpan. Bersifat baca saja dan tidak memiliki endpoint pembuatan, perubahan, maupun penghapusan. Jalurnya adalah /spaces/{spaceId}/webhooks/{webhookId}/logs.

{
  "sys": {
    "id": "3trmXRM3RqbgSnifyg7PWhc01Exam",
    "type": "WebhookLog",
    "space": { "sys": { "id": "HnQ32YiH", "type": "Refer", "targetType": "Space" } },
    "requestId": "3trmXRM3qWnLb7Vd1yPcYs04kKrjq",
    "statusCode": 200,
    "errors": [],
    "eventType": "Create",
    "url": "https://api.dailywear.example/webhooks/products",
    "requestAt": "2026-06-18T11:35:00.100Z",
    "responseAt": "2026-06-18T11:35:00.350Z",
    "request": {
      "url": "https://api.dailywear.example/webhooks/products",
      "method": "POST",
      "headers": { "Content-Type": "application/json", "X-Source": "weegloo" },
      "body": "{\"sys\":{\"type\":\"Content\"}}"
    },
    "response": {
      "url": "https://api.dailywear.example/webhooks/products",
      "headers": { "Content-Type": "application/json" },
      "body": "{\"ok\":true}",
      "statusCode": 200
    },
    "createdBy": { "sys": { "id": "3trmXRM3RqbgSnifyg7PWhk01Examp", "type": "Refer", "targetType": "Webhook" } },
    "createdAt": "2026-06-18T11:35:00.350Z",
    "updatedBy": { "sys": { "id": "3trmXRM3RqbgSnifyg7PWhk01Examp", "type": "Refer", "targetType": "Webhook" } },
    "updatedAt": "2026-06-18T11:35:00.350Z"
  }
}

Semua nilai berada di dalam sys dan tidak ada properti body. Kunci yang tidak bernilai dihilangkan dari respons.

Webhook mana yang menghasilkan catatan itu ditunjuk oleh sys.createdBy. Itu bukan pengguna melainkan Refer ke Webhook tersebut, dan sys.updatedBy juga Webhook yang sama.

PropertiTipeDeskripsi
idstringPengenal unik catatan.
typestringSelalu "WebhookLog".
spaceRefer<Space>Space tempat catatan ini berada.
requestIdstringPengenal pelacakan percobaan pengiriman ini.
statusCodeintegerKode status HTTP dari respons yang diterima.
errorsstring[]Daftar alasan kegagalan. Pada catatan Webhook yang mengirim ke URL, isinya selalu kosong (kode statuslah yang menyatakan kegagalan). Hanya catatan Webhook yang menjalankan Script melalui script yang memuat pesan kegagalan Script tersebut.
eventTypestringIni adalah nama aksi yang menyebabkan pengiriman ini (contoh: Create, Publish). Yang dimuat hanyalah bagian aksinya, bukan bentuk Content.Create yang Anda tulis pada topics.
urlstringURL tujuan pengiriman.
requestAtstring (date-time)Waktu permintaan dikirim.
responseAtstring (date-time)Waktu respons diterima.
requestobjectPermintaan yang dikirim. Struktur turunannya ada di bawah. Dihilangkan pada pengambilan daftar.
responseobjectRespons yang diterima. Struktur turunannya ada di bawah. Dihilangkan pada pengambilan daftar.
createdByRefer<Webhook>Webhook yang menghasilkan catatan ini.
createdAtstring (date-time)Waktu pembuatan catatan.
updatedByRefer<Webhook>Sama dengan createdBy.
updatedAtstring (date-time)Sama dengan createdAt.

request dan response masing-masing memiliki kunci berikut.

  • request: url(URL tujuan permintaan dikirim) · method(metode HTTP) · headers(peta header yang dikirim) · body(string body yang dikirim).
  • response: url(URL tempat respons diterima) · headers(peta header yang diterima) · body(string body yang diterima) · statusCode(kode status yang diterima).

Catatan dari Webhook yang menjalankan Script melalui script berbentuk berbeda. Karena tidak ada alamat tujuan pengiriman, url tidak ada, dan method pada request dipatok menjadi "SCRIPT". body pada request memuat payload yang menyebabkan pengiriman itu, sedangkan body pada response memuat nilai yang dikembalikan Script tersebut (atau pesan kegagalannya).

Nilai header yang secret-nya dinyalakan tersimpan dalam keadaan disamarkan. Nilai sebenarnya tidak tertinggal pada catatan.

Body yang panjang disimpan dalam bentuk yang dipendekkan. Acuannya adalah 65.536 karakter untuk body pada request dan 8.192 karakter untuk body pada response. Jika lebih panjang dari itu, bagian depan dan belakang dipertahankan sedangkan bagian tengahnya dihilangkan, dan jumlah karakter yang dihilangkan dicatat di tempat itu. Jika body-nya JSON, hanya nilai string yang panjang yang dipendekkan dengan cara yang sama agar strukturnya tidak rusak, sehingga kunci dan nilai yang pendek tetap utuh.

Kriteria yang memisahkan keberhasilan dan kegagalan berbeda menurut cara integrasinya. Webhook yang mengirim ke URL berhasil jika responsnya 2xx atau 3xx. Webhook yang menjalankan Script melalui script berhasil jika statusCode kurang dari 400 dan errors kosong. Satu penilaian ini sekaligus menentukan masa penyimpanan di bawah dan tingkat keberhasilan pada status pengiriman.

Pengambilan daftar mengembalikan hasil tanpa request dan response. Sebab nilai bawaan select pada endpoint daftar adalah -sys.response,-sys.request. Untuk melihat sampai ke body permintaan yang dikirim dan respons yang diterima, gunakan pengambilan tunggal, atau tentukan sendiri select untuk menimpa nilai bawaan itu.

Catatan pengiriman yang berhasil hilang setelah 1 jam, dan catatan pengiriman yang gagal setelah 3 hari. Tidak ada field yang memuat waktu kedaluwarsa pada respons, dan catatan itu hilang dengan sendirinya begitu waktunya tiba. Nilai yang harus Anda simpan lebih lama dari itu, simpanlah secara terpisah di server penerima, atau tinggalkan sebagai Content dari Script yang dijalankan melalui script.

Error

Berikut adalah kode yang muncul saat Anda menangani Webhook. Untuk kode yang berlaku umum pada semua sumber daya, lihat Error umum.

KodeKondisi
WGL400042Permintaan pembuatan (POST) dan perubahan penuh (PUT) memuat url dan script sekaligus, atau tidak memuat keduanya.
WGL422061Permintaan perubahan parsial (PATCH) memuat url dan script sekaligus, atau tidak memuat keduanya.
WGL422050url menunjuk ke tujuan yang diblokir seperti jaringan privat atau loopback.

API

Base URL untuk semua endpoint di bawah adalah https://cma.weegloo.com/v1, dan diperlukan Bearer token yang mengautentikasi CMA pada header Authorization. Perubahan (PUT) dan perubahan parsial (PATCH) harus turut mengirim header X-Weegloo-Version (sys.version sumber daya saat ini) untuk kontrol konkurensi optimistis.

  • Content: Data body yang memicu Webhook.
  • Media: Sumber daya file yang dapat memicu Webhook.
  • Script: Endpoint backend deklaratif yang dijalankan melalui script. Termasuk model eksekusi dan izin.
  • SpaceRole: Konfigurasi peran yang menyimpan izin seperti eksekusi Script (Execute).