> ## Documentation Index
> Fetch the complete documentation index at: https://docs.growthbook.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Saved Group Revisions API

> Edit saved groups through draft revisions and publish them with the REST API, including review when required.

The saved group revisions REST API is the programmatic counterpart to the UI workflow described in [Publishing & Approval Flows](https://docs.growthbook.io/features/publishing-and-approval-flows.md#saved-groups). Every change goes through the same draft → review → publish lifecycle, so a draft you start via REST can be reviewed in the UI (and vice versa).

If you just need to read or replace a saved group atomically — and your org does not require approvals — keep using [`POST /saved-groups/{id}`](https://docs.growthbook.io/api/#operation/updateSavedGroup) with the `bypassApproval: true` flag. The endpoints below are for callers who need to stage changes, run approvals, or coordinate with the UI revision flow.

The full endpoint reference lives in the [REST API docs](https://docs.growthbook.io/api.md#tag/saved-group-revisions). This page covers the lifecycle and the request shapes you'll typically reach for.

## Drafts and Publishing

When you edit a saved group via the revision endpoints, GrowthBook creates a draft revision. Drafts hold proposed changes against a snapshot of the saved group at the moment the draft was opened — they don't affect SDK evaluations until they're published.

Open a new draft explicitly:

```bash theme={null}
curl -X POST 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"title": "Add Q2 beta cohort"}'
```

The response contains the new revision and its integer `version`, which you pass to subsequent edit calls:

```json theme={null}
{
  "revision": {
    "id": "rev_...",
    "version": 4,
    "status": "draft",
    "baseSavedGroup":     { "...": "snapshot taken when the draft opened" },
    "proposedSavedGroup": { "...": "snapshot + proposed changes applied" },
    "proposedChanges": []
  }
}
```

Stage a change on the draft. For list saved groups, prefer the incremental endpoints — they're idempotent and stack on top of the current draft state, so multiple add/remove calls accumulate:

```bash theme={null}
curl -X POST 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/4/items/add' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"items": ["user_42", "user_77"]}'
```

For an atomic full replacement, use `PUT .../values`. For condition saved groups, use `PUT .../condition`. Metadata edits (name, owner, description, projects) go through `PUT .../metadata`. Archive or unarchive with `PUT .../archive`.

Publish to apply the draft to the live saved group:

```bash theme={null}
curl -X POST 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/4/publish' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

After publish, the revision status becomes `merged` and the proposed changes are applied to the live saved group.

### Auto-creating a draft on edit

Every field-edit endpoint (`PUT .../metadata`, `PUT .../condition`, `PUT .../values`, `PUT .../archive`, `POST .../items/add`, `POST .../items/remove`) accepts the literal `"new"` in place of a version number. This opens a fresh draft, applies the edit, and returns the revision in one round trip. Pass `revisionTitle` / `revisionComment` to label the auto-created draft:

```bash theme={null}
curl -X PUT 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/new/metadata' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "revisionTitle": "Rename to internal-beta",
    "name": "internal-beta",
    "description": "Cohort moved to the internal-only beta program"
  }'
```

`revisionTitle` and `revisionComment` are ignored when editing an existing draft.

## Revisions

A saved group has one live revision and zero or more open draft revisions. Each revision has a status:

| Status | Meaning |
| - | - |
| `draft` | Open, editable. Authors can keep staging changes. |
| `pending-review` | Submitted for review. Reviewers can approve, comment, or request changes. |
| `changes-requested` | A reviewer asked for changes. Edit the draft and re-request review. |
| `approved` | Approved and ready to publish. |
| `merged` | Published. Terminal. |
| `discarded` | Abandoned. Terminal. |

Use these endpoints to read revisions:

| Endpoint | Use it for |
| - | - |
| `GET /saved-groups-revisions` | List revisions across every saved group. Filter by `savedGroupId`, `status`, `author`, or `mine`. |
| `GET /saved-groups-revisions/{savedGroupId}` | List revisions for one saved group. |
| `GET /saved-groups-revisions/{savedGroupId}/latest` | The most recently updated open draft. 404 if no open draft. `mine=true` filters to your own drafts. |
| `GET /saved-groups-revisions/{savedGroupId}/{version}` | Fetch a specific revision, including `baseSavedGroup`, `proposedSavedGroup`, reviews, activity log. |
| `GET /saved-groups-revisions/{savedGroupId}/{version}/merge-status` | Dry-run merge against the current live state. Returns conflicts and whether they can auto-merge. |

`baseSavedGroup` is the snapshot taken when the draft opened. `proposedSavedGroup` is what the live saved group would look like if the draft were merged right now — useful for previewing changes without interpreting the raw JSON Patch ops in `proposedChanges`.

### Reverting

`POST /saved-groups-revisions/{savedGroupId}/{version}/revert` creates a new revision whose content matches the specified historical revision. Pass `{"strategy": "draft"}` (default) to stage the revert as a draft, or `{"strategy": "publish"}` to publish immediately. Publish obeys the same approval rules as a normal publish.

```bash theme={null}
curl -X POST 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/2/revert' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"strategy": "draft", "title": "Roll back the Q2 cohort change"}'
```

### Discarding

Open drafts you no longer want can be discarded with `POST .../discard`. Merged and already-discarded revisions are rejected.

```bash theme={null}
curl -X POST 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/4/discard' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"reason": "superseded by revision 5"}'
```

## Merge Conflicts

Your draft can diverge from the live saved group if someone else publishes changes while your draft is open. Publishing detects this and rejects the call with `409 Conflict`, including the conflicting fields in the response body.

The recovery flow is to rebase, then re-publish:

```bash theme={null}
# 1. Inspect conflicts
curl 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/4/merge-status' \
  -H 'Authorization: Bearer YOUR_API_KEY'

# 2. Rebase, picking a resolution strategy per conflicting field
curl -X POST 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/4/rebase' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "conflictResolutions": {
      "values": "union",
      "description": "overwrite"
    }
  }'

# 3. Retry publish
curl -X POST 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/4/publish' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

Per-field resolution strategies:

* `overwrite` — keep the draft's value.
* `discard` — keep the live value.
* `union` — concatenate arrays (only valid for `values` on list saved groups). Pass `customValues` to supply your own merged array instead of the default union.

`merge-status` is purely informational — it doesn't lock anything. If you need strict optimistic locking, call `merge-status`, then `publish`, and on `409` re-fetch and retry.

## Approval Flows

Enterprise

**Require Approvals**
is available on Enterprise plans.

When [Saved Group approvals are
required](https://docs.growthbook.io/features/publishing-and-approval-flows.md#saved-group-approval-flows), a
draft must be approved before it can be published. Approval is not required when
the caller has the **Bypass draft approvals** policy in every Project assigned to
the Saved Group, or when the organization enables **REST API always bypasses
approval requirements**.

### Requesting a Review

Move a draft from `draft` to `pending-review`. Reviewers are notified per the org's approval-flow settings.

```bash theme={null}
curl -X POST 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/4/request-review' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

### Reviewing

A reviewer submits a decision with `POST .../submit-review`. `decision` is one of `approve`, `request-changes`, or `comment`. With `blockSelfApproval` enabled (controlled by the org's **Require approval from a non-editor** setting), authors and contributors cannot submit `approve` on their own drafts.

An organization API key reviews as itself, judged on its own role, unless it assumes the role of a member it names with `X-GrowthBook-Requested-By`; then the decision counts as that member's.

```bash theme={null}
curl -X POST 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/4/submit-review' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'X-GrowthBook-Requested-By: alice@example.com' \
  -H 'Content-Type: application/json' \
  -d '{"decision": "approve", "comment": "LGTM"}'
```

The revision's `reviews` array on subsequent reads shows every decision, who made it, and when.

### Publishing with Approvals

Once the revision is `approved`, publish proceeds normally:

```bash theme={null}
curl -X POST 'https://api.growthbook.io/api/v1/saved-groups-revisions/grp_abc123/4/publish' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

There are three ways to publish without an approved revision:

1. **Direct-write bypass** — `POST /saved-groups` and `POST
   /saved-groups/{id}` can send `bypassApproval: true` to update the live Saved
   Group without creating a revision. The caller needs **Bypass draft approvals**
   in every affected Project.
2. **Permission-based publish** — the revision publish endpoint automatically
   skips the approval check for callers with **Bypass draft approvals** in every
   Project assigned to the Saved Group. The `bypassApproval` field on this
   endpoint is accepted for backwards compatibility but does not change the
   result.
3. **Organization-wide REST bypass** — when **REST API always bypasses approval
   requirements** is enabled, REST API requests can publish without approval.

### Permissions

Saved Group lifecycle permissions are independent:

* **Create** creates a Saved Group.
* **Edit** opens and changes drafts, requests review, rebases, and discards
  drafts.
* **Review** approves a draft or requests changes. A plain review comment can
  also be added with the general **Comments** permission.
* **Publish** applies a draft to the live Saved Group and unarchives it.
* **Revert** restores a previously published revision.
* **Archive & delete** archives a Saved Group or permanently deletes one that is
  already archived.
* **Bypass draft approvals** skips required review and allows an out-of-date
  draft to be force-published.

GrowthBook checks permissions again when a draft is published. If the draft
changes the Saved Group's Projects, the caller must have the required permission
in both the current and destination Projects.

A user with only **Revert** or **Archive & delete** can still create and complete
a draft that contains only that action. Adding any unrelated change requires
**Edit** and **Publish** access.
