---
url: /en/paas/system-hook.md
description: >
  Documents the system hook event notification mechanism for CNB PAAS, covering
  callback URL configuration, supported event types, and request body structures
  for Resource Change and User Notify hooks.
---
## Overview

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 |

## Configuration

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 |

## Supported Event Types

The platform currently supports the following events
(the event name is the value of the `event_name` field in the callback):

### Repository Events

| 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 |

### Issue Events

| 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) |

### Pull Request Events

| 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) |

### Organization Events

| Event Name | Description |
|------------|-------------|
| `organization_delete` | Delete organization |
| `organization_transfer` | Organization transfer |
| `organization_member_role_change` | Organization member role change |

### CI Events

| Event Name | Description |
|------------|-------------|
| `ci_notice` | CI notification (triggered only on build failure) |

### User Events

| Event Name | Description |
|------------|-------------|
| `at_users` | @user (appears in Issue/PR content or comments) |
| `user_notify` | User notification (system custom notification message) |

### Artifact Registry Events

| 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 |

## Callback Request

When an event is triggered, the platform sends a POST request to your callback URL.

### 1. Request Headers

| 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 |

### 2. Request Body Structure

#### Resource Change Type

The request body is a JSON array, where each element is a `HookRequestBody` object
with the following core structure:

```text
{
  "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.

#### User Notify Type

The request body is in `ReqSentMessageCard` format,
compatible with WeChat Work messaging API:

```json
{
  "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 |

## Data Structure Details

### Common Fields

| 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 |

### User Information Structure (user / NotifyUsers element)

| 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) |

### Repository Information Structure (repo)

| 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) |

### Organization Information Structure (group)

| 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) |

### Issue Information Structure (issue)

| 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) |

### PR Information Structure (pull\_request)

| 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 |

### PR Review Information Structure (pull\_request\_review)

| Field | Type | Description |
|-------|------|-------------|
| `reviewer_id` | Integer | Reviewer ID |
| `review_state` | String | Review state (`commented` / `approved` / `changes_requested`) |

### Comment Information Structure (comment)

| Field | Type | Description |
|-------|------|-------------|
| `comment_id` | Integer | Comment ID |

### Commit Information Structure (commit, only for `repo_push` event)

| Field | Type | Description |
|-------|------|-------------|
| `pusher` | Object | Pusher info (contains `username`, `nickname`, `user_email`) |
| `commits` | Array | Commit list, each item contains `id`, `message`, `timestamp`, `author`, `committer` |

### CI Build Information Structure (oci\_build, only for `ci_notice` event)

| 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` |

### Registry Information Structure (registry)

| 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) |

### @User Event Additional Fields

| Field | Type | Description |
|-------|------|-------------|
| `at_users_position` | String | @location: `at_issue` / `at_issue_comment` / `at_pull_request` / `at_pull_request_comment` |

## Callback Examples

### Example 1: Code Push (repo\_push)

```json
[
  {
    "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"
      }
    ]
  }
]
```

### Example 2: Issue Status Change (issue\_status\_change)

```json
[
  {
    "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"
      }
    ]
  }
]
```

### Example 3: PR Created (pull\_request\_opened)

```json
[
  {
    "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"
      }
    ]
  }
]
```

### Example 4: Repository Member Role Change (repo\_member\_role\_change)

```json
[
  {
    "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"
      }
    ]
  }
]
```

### Example 5: Artifact Push (artifact\_push)

```json
[
  {
    "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"
      }
    ]
  }
]
```

### Example 6: User Notify Type Callback (User Notify)

```json
{
  "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"
  }
}
```

## Integration Notes

1. **Endpoint Requirements**: The callback URL must support POST requests
   and correctly parse JSON format request bodies.
2. **Response Requirements**: Return HTTP 200 OK status code after processing
   to prevent the platform from retrying.
3. **Security Recommendations**: If `X-CNB-Token` is configured,
   verify this field to ensure the request comes from the platform.
4. **Callback Configuration**: To set up or modify the callback URL,
   contact the platform administrator or use the Admin Management Platform.
5. **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** (`{...}`).
6. **CI Notifications**: The `ci_notice` event is triggered **only on build failure**;
   successful build notifications are not pushed.
7. **Member Role Changes**: Derived (inherited) member changes do not trigger hooks;
   only direct changes trigger them.
