doc/api/runner_controllers.md
{{< details >}}
{{< /details >}}
[!flag] The availability of this feature is controlled by a feature flag. For more information, see the history. This feature is available for testing, but not ready for production use.
{{< history >}}
FF_USE_JOB_ROUTER. This feature is an experiment and subject to the GitLab Testing Agreement.connected field introduced in GitLab 18.10.{{< /history >}}
The runner controllers API allows you to manage runner controllers for CI/CD job admission control. Runner controllers connect to the job router and evaluate jobs against custom policies, deciding whether to admit or reject them. This API provides endpoints to create, read, update, and delete runner controllers.
Prerequisites:
Lists all runner controllers.
GET /runner_controllers
Response:
If successful, returns 200 OK with the following response attributes:
| Attribute | Type | Description |
|---|---|---|
id | integer | The unique identifier of the runner controller. |
description | string | A description for the runner controller. |
state | string | The state of the runner controller. Valid values are disabled (default), enabled, or dry_run. |
created_at | datetime | The date and time when the runner controller was created. |
updated_at | datetime | The date and time when the runner controller was last updated. |
Example request:
curl --request GET \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/runner_controllers"
Example response:
[
{
"id": 1,
"description": "Runner controller",
"state": "enabled",
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-02T00:00:00Z"
},
{
"id": 2,
"description": "Another runner controller",
"state": "disabled",
"created_at": "2026-01-03T00:00:00Z",
"updated_at": "2026-01-04T00:00:00Z"
}
]
Retrieves details of a specific runner controller by its ID.
GET /runner_controllers/:id
Response:
If successful, returns 200 OK with the following response attributes:
| Attribute | Type | Description |
|---|---|---|
id | integer | The unique identifier of the runner controller. |
description | string | A description for the runner controller. |
state | string | The state of the runner controller. Valid values are disabled (default), enabled, or dry_run. |
connected | boolean | Whether the runner controller is currently connected. A runner controller is considered connected when it uses at least one of its active tokens within the last hour. |
created_at | datetime | The date and time when the runner controller was created. |
updated_at | datetime | The date and time when the runner controller was last updated. |
Example request:
curl --request GET \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/runner_controllers/1"
Example response:
{
"id": 1,
"description": "Runner controller",
"state": "enabled",
"connected": true,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-02T00:00:00Z"
}
Registers a new runner controller.
POST /runner_controllers
Supported attributes:
| Attribute | Type | Required | Description |
|---|---|---|---|
description | string | No | A description for the runner controller. |
state | string | No | The state of the runner controller. Valid values are disabled (default), enabled, or dry_run. |
Response:
If successful, returns 201 Created with the following response attributes:
| Attribute | Type | Description |
|---|---|---|
id | integer | The unique identifier of the runner controller. |
description | string | A description for the runner controller. |
state | string | The state of the runner controller. Valid values are disabled (default), enabled, or dry_run. |
created_at | datetime | The date and time when the runner controller was created. |
updated_at | datetime | The date and time when the runner controller was last updated. |
Example request:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{"description": "New runner controller", "state": "dry_run"}' \
--url "https://gitlab.example.com/api/v4/runner_controllers"
Example response:
{
"id": 3,
"description": "New runner controller",
"state": "dry_run",
"created_at": "2026-01-05T00:00:00Z",
"updated_at": "2026-01-05T00:00:00Z"
}
Updates the details of an existing runner controller by its ID.
PUT /runner_controllers/:id
Supported attributes:
| Attribute | Type | Required | Description |
|---|---|---|---|
description | string | No | A description for the runner controller. |
state | string | No | The state of the runner controller. Valid values are disabled (default), enabled, or dry_run. |
If successful, returns 200 OK with the following response attributes:
| Attribute | Type | Description |
|---|---|---|
id | integer | The unique identifier of the runner controller. |
description | string | A description for the runner controller. |
state | string | The state of the runner controller. Valid values are disabled (default), enabled, or dry_run. |
created_at | datetime | The date and time when the runner controller was created. |
updated_at | datetime | The date and time when the runner controller was last updated. |
Example request:
curl --request PUT \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{"description": "Updated runner controller", "state": "enabled"}' \
--url "https://gitlab.example.com/api/v4/runner_controllers/3"
Example response:
{
"id": 3,
"description": "Updated runner controller",
"state": "enabled",
"created_at": "2026-01-05T00:00:00Z",
"updated_at": "2026-01-06T00:00:00Z"
}
Delete a specific runner controller by its ID.
DELETE /runner_controllers/:id
If successful, returns 204 No Content.
curl --request DELETE \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/runner_controllers/3"
Runner controller scopes define which jobs a runner controller evaluates for admission control.
A runner controller must have at least one scope to receive admission requests. Without a scope,
the controller remains inactive even when its state is enabled or dry_run.
Runner controller scopes support two mutually exclusive scoping types:
A runner controller can have either an instance scope or one or more runner scopes, but not both.
[!note] Only instance and runner scopes are available. Additional scope types (group, project) are proposed in issue 586419.
Lists all scopes configured for a specific runner controller:
GET /runner_controllers/:id/scopes
Supported attributes:
| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The ID of the runner controller. |
If successful, returns 200 OK and the following
response attributes:
| Attribute | Type | Description |
|---|---|---|
instance_level_scopings | object array | List of instance scopes for the runner controller. |
instance_level_scopings[].created_at | datetime | The date and time when the scope was created. |
instance_level_scopings[].updated_at | datetime | The date and time when the scope was last updated. |
runner_level_scopings | object array | List of runner scopes for the runner controller. |
runner_level_scopings[].runner_id | integer | The ID of the runner. |
runner_level_scopings[].created_at | datetime | The date and time when the scope was created. |
runner_level_scopings[].updated_at | datetime | The date and time when the scope was last updated. |
Example request:
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/runner_controllers/1/scopes"
Example response:
{
"instance_level_scopings": [
{
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:00:00Z"
}
],
"runner_level_scopings": []
}
Adds an instance scope to a runner controller. When added, the runner controller evaluates jobs for all runners in the GitLab instance.
A runner controller can have only one instance scope. If an instance scope already exists, this endpoint returns an error.
POST /runner_controllers/:id/scopes/instance
Supported attributes:
| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The ID of the runner controller. |
If successful, returns 201 Created and the following
response attributes:
| Attribute | Type | Description |
|---|---|---|
created_at | datetime | The date and time when the scoping was created. |
updated_at | datetime | The date and time when the scoping was last updated. |
Example request:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/runner_controllers/1/scopes/instance"
Example response:
{
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:00:00Z"
}
Removes an instance scope from a runner controller.
DELETE /runner_controllers/:id/scopes/instance
Supported attributes:
| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The ID of the runner controller. |
If successful, returns 204 No Content.
Example request:
curl --request DELETE \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/runner_controllers/1/scopes/instance"
{{< history >}}
{{< /history >}}
Adds a runner scope to a runner controller. When added, the runner controller evaluates jobs only for the specified runner.
A runner controller with an instance scope cannot have runner scopes. Remove the instance scope before adding runner scopes.
POST /runner_controllers/:id/scopes/runners/:runner_id
Supported attributes:
| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The ID of the runner controller. |
runner_id | integer | Yes | The ID of the runner. Must be an instance runner. |
If successful, returns 201 Created and the following
response attributes:
| Attribute | Type | Description |
|---|---|---|
runner_id | integer | The ID of the runner. |
created_at | datetime | The date and time when the scope was created. |
updated_at | datetime | The date and time when the scope was last updated. |
Example request:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/runner_controllers/1/scopes/runners/5"
Example response:
{
"runner_id": 5,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:00:00Z"
}
{{< history >}}
{{< /history >}}
Removes a runner scope from a runner controller.
DELETE /runner_controllers/:id/scopes/runners/:runner_id
Supported attributes:
| Attribute | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The ID of the runner controller. |
runner_id | integer | Yes | The ID of the runner. |
If successful, returns 204 No Content.
Example request:
curl --request DELETE \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/runner_controllers/1/scopes/runners/5"