# Update a repository ruleset

> Change a repository ruleset.

<div class="g1t-endpoint"><span class="g1t-method" data-method="put">PUT</span><code>/repos/{owner}/{name}/rulesets/{id}</code></div>

Fields left out stay as they are; rules and bypass_actors, when given, replace the whole list. Takes the Admin role.

Fields left out stay as they are. `rules` and `bypass_actors`, when given, replace the whole list.

- **Authentication:** Required. Send an [access token](/reference/api/#authentication) as `Authorization: Bearer`.
- **MCP tool:** [`repository`](/reference/mcp/#repository) with `action` `update_ruleset`, and the same inputs
- **Scope:** An access token needs [`repo:admin`](/guides/authentication/#scopes).

## Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `owner` | string | Yes | The workspace that owns the repository. |
| `name` | string | Yes | The repository's name. |
| `id` | string | Yes | The ruleset's id: rs_… |

## Body parameters

Send a JSON object. Names are `snake_case`, as in responses; the `camelCase` spelling is accepted too.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `ruleset_name` | string | No | What people call it, at most 100 characters. A ruleset as exported names it `name`, which is read too. |
| `enforcement` | string | No | active: its rules hold. evaluate: nothing is refused, and what would have been is recorded. disabled: kept, not evaluated. Default active. One of `active`, `evaluate`, `disabled`. |
| `target` | string | No | What its name conditions match. Default branch. One of `branch`, `tag`. |
| `conditions` | object | No |  |
| `conditions.ref_name` | object | No | Which branches or tags: include and exclude, each a list of fnmatch patterns (* within a path segment, ** across them), ~DEFAULT_BRANCH or ~ALL. |
| `conditions.ref_name.include` | array of strings | No |  |
| `conditions.ref_name.exclude` | array of strings | No |  |
| `bypass_actors` | array of objects | No | Who it does not hold for. Nobody bypasses unless listed, g1t included. kind role takes read, triage, write, maintain, admin (that role or higher) or owner; team its slug or workspace/slug; user a username; token a token id, or workspace for any of the workspace's tokens; g1t no value. mode always (pushes and merges) or pull_requests (merges only; a person merging asks to, with bypass_rules). |
| `bypass_actors[].kind` | string | Yes | One of `role`, `team`, `user`, `token`, `g1t`. |
| `bypass_actors[].value` | string | No |  |
| `bypass_actors[].mode` | string | No | One of `always`, `pull_requests`. |
| `rules` | array of objects | No | Its rules. Each: type, parameters (left-out parameters take their defaults) and applies_to (everyone, agents or people). See the Rules guide for every type's parameters. |
| `rules[].type` | string | Yes |  |
| `rules[].parameters` | object | No |  |
| `rules[].applies_to` | string | No | One of `everyone`, `agents`, `people`. |

## Example request

```sh
curl -X PUT https://api.g1t.sh/repos/flagon-io/hello/rulesets/rs_01kq3a8b9c0d1e2f3g4h5j6k7m \
  -H "Authorization: Bearer $G1T_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enforcement": "evaluate"
  }'
```

## Example response

A successful request answers `200` with:

```json
{
  "id": "rs_01kq3a8b9c0d1e2f3g4h5j6k7m",
  "level": "repository",
  "workspace": "flagon-io",
  "repo_id": "rep_01kq0f3a7b8c9d0e1f2g3h4j5k",
  "repository": "flagon-io/hello",
  "name": "Protect main",
  "enforcement": "evaluate",
  "target": "branch",
  "conditions": {
    "ref_name": {
      "include": [
        "~DEFAULT_BRANCH"
      ],
      "exclude": []
    }
  },
  "bypass_actors": [
    {
      "kind": "role",
      "value": "admin",
      "mode": "pull_requests"
    }
  ],
  "rules": [
    {
      "type": "deletion",
      "parameters": {},
      "applies_to": "everyone"
    },
    {
      "type": "non_fast_forward",
      "parameters": {},
      "applies_to": "everyone"
    },
    {
      "type": "pull_request",
      "parameters": {
        "required_approvals": 1,
        "count_agent_approvals": true,
        "dismiss_stale_reviews_on_push": true,
        "require_code_owner_review": true,
        "require_last_push_approval": false,
        "allowed_merge_methods": []
      },
      "applies_to": "everyone"
    },
    {
      "type": "required_status_checks",
      "parameters": {
        "checks": [
          {
            "context": "CI",
            "integration": "actions"
          }
        ],
        "strict": true,
        "paths": [],
        "allow_bypass_on_merge": false
      },
      "applies_to": "everyone"
    },
    {
      "type": "pull_request",
      "parameters": {
        "required_approvals": 1,
        "count_agent_approvals": false,
        "dismiss_stale_reviews_on_push": false,
        "require_code_owner_review": false,
        "require_last_push_approval": false,
        "allowed_merge_methods": []
      },
      "applies_to": "agents"
    },
    {
      "type": "file_path_restriction",
      "parameters": {
        "restricted_file_paths": [
          ".g1t/workflows/**",
          "CODEOWNERS"
        ]
      },
      "applies_to": "agents"
    }
  ],
  "created_by": "syntaqx",
  "created_at": "2026-10-07T14:02:11.318Z",
  "updated_by": "syntaqx",
  "updated_at": "2026-10-07T14:02:11.318Z"
}
```

## Errors

A failed request answers with one of these statuses and a body like `{"error": {"code": "not_found", "message": "Repository not found."}}`. See [errors](/reference/api/#errors).

| Status | Code | When |
| --- | --- | --- |
| 401 | `unauthenticated` | A token is required, or the one sent is not valid. |
| 403 | `forbidden` | The token is valid but not allowed to do this, such as a member-only change or an agent token outside its repository. |
| 404 | `not_found` | It does not exist, or you cannot see it. |
| 409 | `conflict` | The request conflicts with the current state. |
| 422 | `invalid` | The input is not valid. `message` says which field and why. |
