diff --git a/doc/api/groups.md b/doc/api/groups.md
index cabfe85619c8ca491270cd8c575ff95038e690c9..87e0d0b4665a908f7b8ca81ebbed4eefca51aff7 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -1588,6 +1588,8 @@ GET /groups/:id/hooks/:hook_id
 {
   "id": 1,
   "url": "http://example.com/hook",
+  "name": "Hook name",
+  "description": "Hook description",
   "group_id": 3,
   "push_events": true,
   "push_events_branch_filter": "",
@@ -1627,8 +1629,10 @@ POST /groups/:id/hooks
 | -----------------------------| -------------- |----------| ----------- |
 | `id`                         | integer/string | yes      | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) |
 | `url`                        | string         | yes      | The hook URL |
+| `name`                       | string         | no       | Name of the hook ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460887) in GitLab 17.0) |
+| `description`                | string         | no       | Description of the hook ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460887) in GitLab 17.0) |
 | `push_events`                | boolean        | no       | Trigger hook on push events |
-| `push_events_branch_filter`  | string         | No       | Trigger hook on push events for matching branches only. |
+| `push_events_branch_filter`  | string         | no       | Trigger hook on push events for matching branches only |
 | `issues_events`              | boolean        | no       | Trigger hook on issues events |
 | `confidential_issues_events` | boolean        | no       | Trigger hook on confidential issues events |
 | `merge_requests_events`      | boolean        | no       | Trigger hook on merge requests events |
@@ -1644,8 +1648,8 @@ POST /groups/:id/hooks
 | `member_events`              | boolean        | no       | Trigger hook on member events |
 | `enable_ssl_verification`    | boolean        | no       | Do SSL verification when triggering the hook |
 | `token`                      | string         | no       | Secret token to validate received payloads; not returned in the response |
-| `resource_access_token_events` | boolean         | no       | Trigger hook on project access token expiry events. |
-| `custom_webhook_template`    | string         | No       | Custom webhook template for the hook. |
+| `resource_access_token_events` | boolean         | no       | Trigger hook on project access token expiry events |
+| `custom_webhook_template`    | string         | no       | Custom webhook template for the hook |
 
 ### Edit group hook
 
@@ -1660,8 +1664,10 @@ PUT /groups/:id/hooks/:hook_id
 | `id`                         | integer or string | yes      | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding). |
 | `hook_id`                    | integer        | yes      | The ID of the group hook. |
 | `url`                        | string         | yes      | The hook URL. |
+| `name`                       | string         | no       | Name of the hook ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460887) in GitLab 17.0). |
+| `description`                | string         | no       | Description of the hook ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460887) in GitLab 17.0). |
 | `push_events`                | boolean        | no       | Trigger hook on push events. |
-| `push_events_branch_filter`  | string         | No       | Trigger hook on push events for matching branches only. |
+| `push_events_branch_filter`  | string         | no       | Trigger hook on push events for matching branches only. |
 | `issues_events`              | boolean        | no       | Trigger hook on issues events. |
 | `confidential_issues_events` | boolean        | no       | Trigger hook on confidential issues events. |
 | `merge_requests_events`      | boolean        | no       | Trigger hook on merge requests events. |
@@ -1679,7 +1685,7 @@ PUT /groups/:id/hooks/:hook_id
 | `service_access_tokens_expiration_enforced` | boolean | no | Require service account access tokens to have an expiration date. |
 | `token`                      | string         | no       | Secret token to validate received payloads. Not returned in the response. When you change the webhook URL, the secret token is reset and not retained. |
 | `resource_access_token_events` | boolean      | no       | Trigger hook on project access token expiry events. |
-| `custom_webhook_template`    | string         | No       | Custom webhook template for the hook. |
+| `custom_webhook_template`    | string         | no       | Custom webhook template for the hook. |
 
 ### Delete group hook
 
diff --git a/doc/api/projects.md b/doc/api/projects.md
index b839109cde7c4521b01f7b698294fe7dd47697df..c1a261cdc91ae074de6563c3f6f2b478b722b53e 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -2769,6 +2769,8 @@ GET /projects/:id/hooks/:hook_id
 {
   "id": 1,
   "url": "http://example.com/hook",
+  "name": "Hook name",
+  "description": "Hook description",
   "project_id": 3,
   "push_events": true,
   "push_events_branch_filter": "",
@@ -2806,6 +2808,8 @@ POST /projects/:id/hooks
 |------------------------------|-------------------|----------|-------------|
 | `id`                         | integer or string | Yes      | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding). |
 | `url`                        | string            | Yes      | The hook URL. |
+| `name`                       | string            | No       | Name of the hook ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460887) in GitLab 17.0). |
+| `description`                | string            | No       | Description of the hook ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460887) in GitLab 17.0). |
 | `confidential_issues_events` | boolean           | No       | Trigger hook on confidential issues events. |
 | `confidential_note_events`   | boolean           | No       | Trigger hook on confidential note events. |
 | `deployment_events`          | boolean           | No       | Trigger hook on deployment events. |
@@ -2837,6 +2841,8 @@ PUT /projects/:id/hooks/:hook_id
 | `hook_id`                    | integer           | Yes      | The ID of the project hook. |
 | `id`                         | integer or string | Yes      | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding). |
 | `url`                        | string            | Yes      | The hook URL. |
+| `name`                       | string            | No       | Name of the hook ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460887) in GitLab 17.0). |
+| `description`                | string            | No       | Description of the hook ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460887) in GitLab 17.0). |
 | `confidential_issues_events` | boolean           | No       | Trigger hook on confidential issues events. |
 | `confidential_note_events`   | boolean           | No       | Trigger hook on confidential note events. |
 | `deployment_events`          | boolean           | No       | Trigger hook on deployment events. |
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
index 5cbccca67b0b9262b6ba1e71600c87f294f5ec6f..465eb4d72e16fa55a1e1ac095a6b5cb6a254b707 100644
--- a/doc/api/system_hooks.md
+++ b/doc/api/system_hooks.md
@@ -40,6 +40,8 @@ Example response:
   {
     "id":1,
     "url":"https://gitlab.example.com/hook",
+    "name": "Hook name",
+    "description": "Hook description",
     "created_at":"2016-10-31T12:32:15.192Z",
     "push_events":true,
     "tag_push_events":false,
@@ -75,6 +77,8 @@ Example response:
   {
     "id": 1,
     "url": "https://gitlab.example.com/hook",
+    "name": "Hook name",
+    "description": "Hook description",
     "created_at": "2016-10-31T12:32:15.192Z",
     "push_events": true,
     "tag_push_events": false,
@@ -96,6 +100,8 @@ POST /hooks
 | Attribute | Type | Required | Description |
 | --------- | ---- | -------- | ----------- |
 | `url` | string | yes | The hook URL |
+| `name` | string | no | Name of the hook ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460887) in GitLab 17.0) |
+| `description` | string | no | Description of the hook ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460887) in GitLab 17.0) |
 | `token` | string | no | Secret token to validate received payloads; this isn't returned in the response |
 | `push_events` | boolean |  no | When true, the hook fires on push events |
 | `tag_push_events` | boolean | no | When true, the hook fires on new tags being pushed |
@@ -116,6 +122,8 @@ Example response:
   {
     "id":1,
     "url":"https://gitlab.example.com/hook",
+    "name": "Hook name",
+    "description": "Hook description",
     "created_at":"2016-10-31T12:32:15.192Z",
     "push_events":true,
     "tag_push_events":false,
diff --git a/ee/lib/api/group_hooks.rb b/ee/lib/api/group_hooks.rb
index b253bb437b2a17eec2543652e4329172d1c1ac0f..23b96a78444d59bddb348317c87be6673c7259f8 100644
--- a/ee/lib/api/group_hooks.rb
+++ b/ee/lib/api/group_hooks.rb
@@ -22,6 +22,8 @@ def hook_scope
       end
 
       params :group_hook_properties do
+        optional :name, type: String, desc: 'Name of the hook'
+        optional :description, type: String, desc: 'Description of the hook'
         optional :push_events, type: Boolean, desc: "Trigger hook on push events"
         optional :push_events_branch_filter, type: String, desc: "Respond to push events only on branches that match this filter"
         optional :issues_events, type: Boolean, desc: "Trigger hook on issues events"
diff --git a/ee/spec/factories/group_hooks.rb b/ee/spec/factories/group_hooks.rb
index 6b3a4825967572814c4aed9108395d398292e460..435df647392718e4d3998c68df0efb86f186e834 100644
--- a/ee/spec/factories/group_hooks.rb
+++ b/ee/spec/factories/group_hooks.rb
@@ -3,6 +3,9 @@
 FactoryBot.define do
   factory :group_hook do
     url { generate(:url) }
+    name { generate(:name) }
+    description { "Description of #{name}" }
+
     group
 
     trait :all_events_enabled do
diff --git a/ee/spec/fixtures/api/schemas/public_api/v4/group_hook.json b/ee/spec/fixtures/api/schemas/public_api/v4/group_hook.json
index befb98d647763e3ce77bec8e760ba369090612cd..6570b0703363895f12092bb25dfb326e306329ab 100644
--- a/ee/spec/fixtures/api/schemas/public_api/v4/group_hook.json
+++ b/ee/spec/fixtures/api/schemas/public_api/v4/group_hook.json
@@ -39,6 +39,18 @@
     "url": {
       "type": "string"
     },
+    "name": {
+      "type": [
+        "string",
+        "null"
+      ]
+    },
+    "description": {
+      "type": [
+        "string",
+        "null"
+      ]
+    },
     "created_at": {
       "type": "string",
       "format": "date-time"
diff --git a/lib/api/entities/hook.rb b/lib/api/entities/hook.rb
index 61f3d60bd48a25c3fd01dd372d20ca8f8872e3ce..7e79e18bf95dc631c15c6bf6081d63cea868d801 100644
--- a/lib/api/entities/hook.rb
+++ b/lib/api/entities/hook.rb
@@ -5,6 +5,8 @@ module Entities
     class Hook < Grape::Entity
       expose :id, documentation: { type: 'string', example: 1 }
       expose :url, documentation: { type: 'string', example: 'https://webhook.site' }
+      expose :name, documentation: { type: 'string', example: 'Hook name' }
+      expose :description, documentation: { type: 'string', example: 'Hook description' }
       expose :created_at, documentation: { type: 'dateTime', example: '2012-05-28T04:42:42-07:00' }
       expose :push_events, documentation: { type: 'boolean' }
       expose :tag_push_events, documentation: { type: 'boolean' }
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index 58f449be4940af8360125e0f55fd1b1a19cccc16..aa831bfb40c78ad07fe7fbb96d9aad5d43e4819e 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -22,6 +22,8 @@ def hook_scope
       end
 
       params :common_hook_parameters do
+        optional :name, type: String, desc: 'Name of the hook'
+        optional :description, type: String, desc: 'Description of the hook'
         optional :push_events, type: Boolean, desc: "Trigger hook on push events"
         optional :issues_events, type: Boolean, desc: "Trigger hook on issues events"
         optional :confidential_issues_events, type: Boolean, desc: "Trigger hook on confidential issues events"
diff --git a/lib/api/system_hooks.rb b/lib/api/system_hooks.rb
index 9e96cbbb0452afada9f3b6d9611a7eba2702c01d..1633f75185f9e7118fe2ae41834524c63c34d771 100644
--- a/lib/api/system_hooks.rb
+++ b/lib/api/system_hooks.rb
@@ -22,6 +22,8 @@ def hook_scope
       end
 
       params :hook_parameters do
+        optional :name, type: String, desc: 'Name of the hook'
+        optional :description, type: String, desc: 'Description of the hook'
         optional :token, type: String,
                          desc: "Secret token to validate received payloads; this isn't returned in the response"
         optional :push_events, type: Boolean, desc: 'When true, the hook fires on push events'
diff --git a/spec/factories/project_hooks.rb b/spec/factories/project_hooks.rb
index 34797bd933e553c801d9a5266bcc98fc8cf5b950..cbff2e6ea154272333800d2eed446afb401b46aa 100644
--- a/spec/factories/project_hooks.rb
+++ b/spec/factories/project_hooks.rb
@@ -3,6 +3,8 @@
 FactoryBot.define do
   factory :project_hook do
     url { generate(:url) }
+    name { generate(:name) }
+    description { "Description of #{name}" }
     enable_ssl_verification { false }
     project
 
diff --git a/spec/factories/system_hooks.rb b/spec/factories/system_hooks.rb
index a2d163a060fa5c555819e85eced0455936812e25..94eb889ca048ecc117ade8fe169e01309b0279a2 100644
--- a/spec/factories/system_hooks.rb
+++ b/spec/factories/system_hooks.rb
@@ -3,5 +3,7 @@
 FactoryBot.define do
   factory :system_hook do
     url { generate(:url) }
+    name { generate(:name) }
+    description { "Description of #{name}" }
   end
 end
diff --git a/spec/fixtures/api/schemas/public_api/v4/project_hook.json b/spec/fixtures/api/schemas/public_api/v4/project_hook.json
index 9fb14513525fdbbccac6d54fc120004729916cc6..e9eed84c4dc0009ca56c7d24d33cfc7c71e7b9f4 100644
--- a/spec/fixtures/api/schemas/public_api/v4/project_hook.json
+++ b/spec/fixtures/api/schemas/public_api/v4/project_hook.json
@@ -27,7 +27,9 @@
     "resource_access_token_events"
   ],
   "optional": [
-    "url_variables"
+    "url_variables",
+    "name",
+    "description"
   ],
   "properties": {
     "id": {
@@ -39,6 +41,18 @@
     "url": {
       "type": "string"
     },
+    "name": {
+      "type": [
+        "string",
+        "null"
+      ]
+    },
+    "description": {
+      "type": [
+        "string",
+        "null"
+      ]
+    },
     "created_at": {
       "type": "string",
       "format": "date-time"
diff --git a/spec/fixtures/api/schemas/public_api/v4/system_hook.json b/spec/fixtures/api/schemas/public_api/v4/system_hook.json
index 62154d92acffccfc9be872e6639c6c9fc2723e57..200cd8f8bdad8f1d9e7260f3424f9a62d8e9adbb 100644
--- a/spec/fixtures/api/schemas/public_api/v4/system_hook.json
+++ b/spec/fixtures/api/schemas/public_api/v4/system_hook.json
@@ -21,6 +21,18 @@
     "url": {
       "type": "string"
     },
+    "name": {
+      "type": [
+        "string",
+        "null"
+      ]
+    },
+    "description": {
+      "type": [
+        "string",
+        "null"
+      ]
+    },
     "created_at": {
       "type": "string"
     },
diff --git a/spec/lib/api/entities/hook_spec.rb b/spec/lib/api/entities/hook_spec.rb
index 9b1db1ad258d12f679ea5ddcbc41900fb2fb1fc5..ae1337586d794e5aad2dd3ccc487688e9570c513 100644
--- a/spec/lib/api/entities/hook_spec.rb
+++ b/spec/lib/api/entities/hook_spec.rb
@@ -10,9 +10,9 @@
   subject(:json) { entity.as_json }
 
   it 'exposes correct attributes' do
-    expect(json.keys).to contain_exactly(:alert_status, :created_at, :disabled_until, :enable_ssl_verification, :id,
-      :merge_requests_events, :push_events, :repository_update_events, :tag_push_events, :url, :url_variables,
-      :custom_webhook_template
+    expect(json.keys).to contain_exactly(
+      :id, :name, :description, :alert_status, :created_at, :disabled_until, :enable_ssl_verification, :tag_push_events,
+      :merge_requests_events, :push_events, :repository_update_events, :url, :url_variables, :custom_webhook_template
     )
   end
 
diff --git a/spec/support/shared_examples/requests/api/hooks_shared_examples.rb b/spec/support/shared_examples/requests/api/hooks_shared_examples.rb
index 7dd5e9ca86ee25d10e37d7c30b3232e1ecde8137..862876ab4e8572c76343c9e708388fb1b7ec884f 100644
--- a/spec/support/shared_examples/requests/api/hooks_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/hooks_shared_examples.rb
@@ -50,6 +50,8 @@ def hook_param_overrides
 
   let(:update_params) do
     {
+      name: 'Updated name',
+      description: 'Updated description',
       push_events: false,
       job_events: true,
       push_events_branch_filter: 'updated-branch-filter'