System Hook is an event notification mechanism provided by the platform. When a specified event occurs on the platform (such as code push, Issue change, PR operation, artifact registry change, etc.), the platform sends an HTTP POST request to your pre-configured callback URL, pushing the event content to your system. You only need to provide a callback endpoint that can receive POST requests to get real-time event notifications.
System Hooks support two types:
| Type | Description | Request Body Format |
|---|
| Resource Change | Pushes complete resource change event data, including repository, Issue, PR and other structured information | HookRequestBody JSON |
| User Notify | Pushes formatted notification messages, compatible with instant messaging tools like WeChat Work | ReqSentMessageCard JSON |
Log in to the Admin Management Platform, then navigate to Admin Console → System Hook Configuration → Create System Hook.
Configuration parameters:
| Parameter | Type | Required | Description |
|---|
| URL | String | Yes | Callback URL, the HTTP(S) endpoint to receive event notifications |
| Type | Enum | Yes | Resource Change or User Notify |
| Setting | String | Yes | Subscribed event types, supports multiple selection, comma-separated |
| Token | String | No | Authentication token, sent via X-CNB-Token header when configured, used to verify the request source |
The platform currently supports the following events (the event name is the value of the event_name field in the callback):
| Event Name | Description |
|---|
repo_archive | Archive repository |
repo_default_branch_change | Repository default branch change |
repo_update | Update repository |
repo_delete | Delete repository |
repo_transfer | Repository transfer |
repo_non_compliant | Repository content non-compliant |
repo_member_role_change | Repository member role change |
repo_push | Code push |
| Event Name | Description |
|---|
issue_opened | Issue created |
issue_comment_add | Issue new comment |
issue_assignee_add | Issue new assignee |
issue_status_change | Issue status change (open/close/reopen) |
| Event Name | Description |
|---|
pull_request_opened | PR created |
pull_request_comment_add | PR new comment |
pull_request_assignee_add | PR new assignee |
pull_request_reviewer_add | PR new reviewer |
pull_request_status_change | PR status change (merge/close/reopen) |
pull_request_review_add | PR new review (comment only/approve/changes requested) |
| Event Name | Description |
|---|
organization_delete | Delete organization |
organization_transfer | Organization transfer |
organization_member_role_change | Organization member role change |
| Event Name | Description |
|---|
ci_notice | CI notification (triggered only on build failure) |
| Event Name | Description |
|---|
at_users | @user (appears in Issue/PR content or comments) |
user_notify | User notification (system custom notification message) |
| Event Name | Description |
|---|
registry_create | Registry created |
registry_delete | Registry deleted |
artifact_push | Artifact pushed |
artifact_delete | Artifact deleted |
artifact_enable | Artifact enabled |
artifact_disable | Artifact disabled |
When an event is triggered, the platform sends a POST request to your callback URL.
| Header | Value | Description |
|---|
Content-Type | application/json;charset=utf-8 | Fixed value, request body is JSON format |
X-CNB-Event | System Hook | Fixed value, identifies this as a system hook event |
X-CNB-Token | ${token} | Optional, only present when an authentication token is configured, used to verify the request source |
The request body is a JSON array, where each element is a HookRequestBody object with the following core structure:
{
"event_name": "event type",
"user": {
"id": "user ID",
"username": "username",
"nickname": "user nickname",
"email": "email",
"type": 1,
"access": "DEVELOPER"
},
"repo": { "/* repository info */" },
"group": { "/* organization info */" },
"issue": { "/* issue info */" },
"pull_request": { "/* PR info */" },
"pull_request_review": { "/* PR review info */" },
"at_users_position": "at_issue",
"comment": { "/* comment info */" },
"commit": { "/* commit info */" },
"oci_build": { "/* CI build info */" },
"registry": { "/* registry info */" },
"content": "notification content",
"NotifyUsers": [ "/* list of users to notify */" ]
}
Note: Business fields appear on demand based on the event type; not all fields exist simultaneously. event_name, user, and NotifyUsers are common fields.
The request body is in ReqSentMessageCard format, compatible with WeChat Work messaging API:
{
"touser": "UserID1|UserID2|UserID3",
"msgtype": "text",
"text": {
"content": "Notification message content"
}
}
| Field | Description |
|---|
touser | List of user IDs to receive the message, separated by |, up to 1000 |
msgtype | Message type, fixed as text |
text.content | Message content, up to 2048 bytes |
| Field | Type | Description |
|---|
event_name | String | Required, event type (corresponding to the event list above) |
user | Object | Required, user information of the event trigger |
NotifyUsers | Array | Required, list of users to notify |
| Field | Type | Description |
|---|
id | String | User unique identifier |
username | String | Username |
nickname | String | User nickname |
email | String | Email |
type | Integer | User type (0-WeChat user / 1-OAuth user / 2-Test user / 3-Bot / 4-IOA user) |
access | String | User permission role under the resource (GUEST / REPORTER / DEVELOPER / MASTER / OWNER) |
old_access | String | Old permission role (only for member role change events) |
| Field | Type | Description |
|---|
id | String | Repository ID |
name | String | Repository name |
path | String | Repository full path (e.g., group/repo) |
old_path | String | Repository old path (only for transfer events) |
description | String | Repository description |
visibility_level | String | Visibility (private / public / secret) |
status | String | Repository status (active / archived) |
web_url | String | Repository web URL |
star_count | Integer | Star count |
fork_count | Integer | Fork count |
created_at | String | Creation time (RFC3339) |
updated_at | String | Update time (RFC3339) |
| Field | Type | Description |
|---|
id | String | Organization ID |
name | String | Organization name |
path | String | Organization full path |
old_path | String | Organization old path (only for transfer events) |
description | String | Organization description |
remark | String | Organization remark |
site | String | Organization website |
email | String | Organization email |
member_count | Integer | Member count |
created_at | String | Creation time (RFC3339) |
| Field | Type | Description |
|---|
number | Integer | Issue number |
title | String | Issue title |
state | String | State (reopen / closed / created) |
priority | String | Priority |
label | Array | Label list, each item contains name, description, color |
associated_pull_request_counts | Integer | Associated PR count |
comment_counts | Integer | Comment count |
comment_id | Integer | Comment ID (only for comment events) |
| Field | Type | Description |
|---|
number | Integer | PR number |
title | String | PR title |
state | String | State (merged / closed / reopen / created / submitted) |
src_ref | String | Source branch |
target_ref | String | Target branch |
build_status | String | CI build status |
mergeable_state | String | Mergeable state |
label | Array | Label list |
associated_issue_counts | Integer | Associated Issue count |
comment_counts | Integer | Comment count |
| Field | Type | Description |
|---|
reviewer_id | Integer | Reviewer ID |
review_state | String | Review state (commented / approved / changes_requested) |
| Field | Type | Description |
|---|
comment_id | Integer | Comment ID |
| Field | Type | Description |
|---|
pusher | Object | Pusher info (contains username, nickname, user_email) |
commits | Array | Commit list, each item contains id, message, timestamp, author, committer |
| Field | Type | Description |
|---|
progress_type | String | Execution type (build) |
status | String | Execution status (triggered only on fail) |
duration | String | Execution duration |
build_data | Object | Build details, contains event, sn, build_log_url, repo_name, event_url, ref_type, ref_diff, ref_url, commit_message_title |
pipeline_data | Object | Pipeline details, contains pipeline_id, pipeline_name, success_pipeline_count, all_pipeline_count, pipeline_fail_msg |
| Field | Type | Description |
|---|
name | String | Registry name |
registry_type | String | Registry type (e.g., docker / helm / docker-model, etc.) |
description | String | Registry description |
visibility_level | String | Visibility |
path | String | Registry path |
pkg_name | String | Artifact package name (only for artifact events) |
pkg_version | String | Artifact version (only for artifact events) |
| Field | Type | Description |
|---|
at_users_position | String | @location: at_issue / at_issue_comment / at_pull_request / at_pull_request_comment |
[
{
"event_name": "repo_push",
"user": {
"id": "1001",
"username": "zhangsan",
"nickname": "Zhang San",
"email": "zhangsan@example.com",
"type": 1,
"access": "OWNER"
},
"repo": {
"id": "2001",
"name": "cnb-platform",
"path": "cnb/cnb-platform",
"description": "CNB Platform",
"visibility_level": "private",
"status": "active",
"web_url": "https://cnb.cool/cnb/cnb-platform",
"star_count": 10,
"fork_count": 3
},
"commit": {
"pusher": {
"username": "zhangsan",
"nickname": "Zhang San",
"user_email": "zhangsan@example.com"
},
"commits": [
{
"id": "abc123def456",
"message": "fix: fix system hook push logic",
"timestamp": "2025-12-12T10:00:00Z",
"author": {
"name": "Zhang San",
"email": "zhangsan@example.com",
"when": "2025-12-12T10:00:00Z",
"username": "zhangsan"
}
}
]
},
"NotifyUsers": [
{
"id": "1001",
"username": "zhangsan",
"nickname": "Zhang San"
}
]
}
]
[
{
"event_name": "issue_status_change",
"user": {
"id": "1001",
"username": "zhangsan",
"nickname": "Zhang San",
"type": 1,
"access": "DEVELOPER"
},
"repo": {
"id": "2001",
"name": "cnb-platform",
"path": "cnb/cnb-platform",
"web_url": "https://cnb.cool/cnb/cnb-platform"
},
"issue": {
"number": 42,
"title": "Fix login page style issue",
"state": "closed",
"priority": "P1",
"label": [
{
"name": "bug",
"description": "",
"color": "#FF0000"
}
],
"associated_pull_request_counts": 1,
"comment_counts": 3
},
"NotifyUsers": [
{
"id": "1002",
"username": "alice",
"nickname": "Alice"
}
]
}
]
[
{
"event_name": "pull_request_opened",
"user": {
"id": "1001",
"username": "zhangsan",
"nickname": "Zhang San",
"type": 1,
"access": "DEVELOPER"
},
"repo": {
"id": "2001",
"name": "cnb-platform",
"path": "cnb/cnb-platform",
"web_url": "https://cnb.cool/cnb/cnb-platform"
},
"pull_request": {
"number": 15,
"title": "feat: add system hook documentation",
"state": "created",
"src_ref": "feature/hooks-doc",
"target_ref": "main",
"build_status": "",
"mergeable_state": "MERGEABLE",
"label": [],
"associated_issue_counts": 0,
"comment_counts": 0
},
"NotifyUsers": [
{
"id": "1003",
"username": "admin",
"nickname": "Admin"
}
]
}
]
[
{
"event_name": "repo_member_role_change",
"user": {
"id": "1003",
"username": "admin",
"nickname": "Admin",
"type": 1,
"access": "OWNER"
},
"repo": {
"id": "2001",
"name": "cnb-platform",
"path": "cnb/cnb-platform",
"web_url": "https://cnb.cool/cnb/cnb-platform"
},
"NotifyUsers": [
{
"id": "1001",
"username": "zhangsan",
"nickname": "Zhang San",
"access": "DEVELOPER",
"old_access": "REPORTER"
}
]
}
]
[
{
"event_name": "artifact_push",
"user": {
"id": "1001",
"username": "zhangsan",
"nickname": "Zhang San",
"type": 1,
"access": "OWNER"
},
"registry": {
"name": "cnb-platform",
"registry_type": "docker",
"path": "cnb/cnb-platform",
"visibility_level": "private",
"pkg_name": "cnb-platform/v1.0.0",
"pkg_version": "v1.0.0"
},
"NotifyUsers": [
{
"id": "1001",
"username": "zhangsan",
"nickname": "Zhang San"
}
]
}
]
{
"touser": "1001|1002",
"msgtype": "text",
"text": {
"content": "zhangsan approved PR #15\n\nfeat: add system hook documentation\nhttps://cnb.cool/cnb/cnb-platform/-/pulls/15"
}
}
- Endpoint Requirements: The callback URL must support POST requests and correctly parse JSON format request bodies.
- Response Requirements: Return HTTP 200 OK status code after processing to prevent the platform from retrying.
- Security Recommendations: If
X-CNB-Token is configured, verify this field to ensure the request comes from the platform. - Callback Configuration: To set up or modify the callback URL, contact the platform administrator or use the Admin Management Platform.
- Data Format:
- Resource Change type request body is a JSON array (
[{...}]), even if there is only one event. - User Notify type request body is a JSON object (
{...}).
- CI Notifications: The
ci_notice event is triggered only on build failure; successful build notifications are not pushed. - Member Role Changes: Derived (inherited) member changes do not trigger hooks; only direct changes trigger them.