> This page is for Data API, version v2 Beta.
> For other versions, use one of these documentation indexes:
> - v2 (default): https://developers.webflow.com/data/v2.0.0/llms.txt
> - v2 Beta: https://developers.webflow.com/data/v2.0.0-beta/llms.txt
> - v1: https://developers.webflow.com/data/v1.0.0/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.webflow.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.webflow.com/_mcp/server.

# Branches

> Manage page branches on Enterprise sites through the Data API (beta) — create, update, merge, publish, and delete branches with async task polling.

The Branch API (beta) exposes [page branching](https://help.webflow.com/hc/en-us/articles/33961237931283-Branching) for Enterprise sites. Use it to create isolated copies of pages, pull changes from main, resolve style and component conflicts, merge back into production, and publish branch previews to staging domains.

All Branch endpoints live under `https://api.webflow.com/beta` and require OAuth scopes prefixed with `branches:`. See [OAuth scopes](/data/reference/scopes) for the full list.

## Enterprise entitlement

Branch endpoints require an Enterprise workspace with the page branching entitlement. If the site is not entitled, every Branch endpoint returns **403** with code `not_enterprise_plan_site`:

```json
{
  "code": "not_enterprise_plan_site",
  "message": "This site is not associated with an Enterprise plan",
  "externalReference": null,
  "details": []
}
```

This matches other Enterprise-only site endpoints such as [Get Site Activity Logs](/data/reference/enterprise/site-activity-logs/list).

## Branch lifecycle and status

Each branch resource includes a computed `status` and a `nextActions` array with follow-up HTTP calls you can make:

| Status          | Meaning                                                    | Typical `nextActions`                                     |
| :-------------- | :--------------------------------------------------------- | :-------------------------------------------------------- |
| `ready`         | No pending tasks, conflicts, or unpulled main changes      | `merge`, `publish`, `delete`                              |
| `needs_update`  | Main has changes the branch has not pulled in yet          | `update`, `merge`, `publish`, `delete`                    |
| `has_conflicts` | Style or component conflicts exist between branch and main | `check_conflicts`, `update`, `merge`, `publish`, `delete` |
| `updating`      | An update-from-main task is queued or running              | `poll_task`                                               |
| `merging`       | A merge-into-main task is queued or running                | `poll_task`                                               |

`nextActions` entries include `action`, `method`, and `href` (a path under `/beta`). Use them as discoverability hints. For `has_conflicts`, start with `check_conflicts` to get conflict ids before calling update or merge with `resolutions`.

## Async operations and task polling

Create, delete, update, and merge are **async**. A successful request returns **202 Accepted** with a task envelope:

```json
{
  "taskId": "a182dc14-eea8-46eb-9756-6a41d4125362",
  "status": "queued",
  "nextActions": [
    {
      "action": "poll_task",
      "method": "GET",
      "href": "/beta/sites/{site_id}/branches/tasks/a182dc14-eea8-46eb-9756-6a41d4125362"
    }
  ]
}
```

Poll [Get Branch Task Status](/data/v2.0.0-beta/reference/enterprise/branches/get-task) until `status` is `finished` or `failed`. For create tasks, read `branchId` from the finished task response.

> **Note**
>
> `DELETE /sites/{site_id}/branches/{branch_id}` returns **202** with a task envelope — not 204.

Publish also returns **202**, but includes `stagingDomain` and `publishedOn` in the response body.

## One branch per page

You can create only **one active branch per page**. Attempting to branch a page that cannot be branched, or that already has an active branch, returns **400** with code `page_cannot_branch`.

## Conflicts and resolutions

When main and a branch both change the same style block or component, the branch enters `has_conflicts`.

1. Call [Get Branch Conflicts](/data/v2.0.0-beta/reference/enterprise/branches/get-conflicts) to list unresolved items.
2. For **update**, include a `resolutions` entry for **every** conflict, matched by `(type, id)` from the conflicts response (IDs like `default-body` are valid — not every conflict id is an ObjectId).
3. For **merge**, omit `resolutions` on the first attempt when conflicts exist. The API returns **409** with code `branch_merge_conflict` and the conflict list in `details`. If you supply resolutions but miss any conflict, the API returns **400** `invalid_resolution` instead. Retry [Merge Branch](/data/v2.0.0-beta/reference/enterprise/branches/merge) with a complete `resolutions` array to resolve and merge in one step.

If resolutions do not cover every conflict, the API returns **400** `invalid_resolution` with the uncovered conflicts in `details` (same shape as `GET .../conflicts`):

```json
{
  "code": "invalid_resolution",
  "message": "Resolutions required for all conflicts. Call GET /conflicts to see unresolved items.",
  "details": [
    { "id": "default-body", "name": "heading", "type": "style" }
  ]
}
```

## Sync pending (503)

Branch conflict checks force a multiplayer sync. When recent edits are still syncing, list, get, conflicts, update, and merge can return **503** with code `branch_sync_pending`:

```json
{
  "code": "branch_sync_pending",
  "message": "Recent edits are still syncing and conflicts cannot be verified yet. Please try again in a moment.",
  "details": []
}
```

Retry after a short delay with exponential backoff. This is common on [List Branches](/data/v2.0.0-beta/reference/enterprise/branches/list) when one branch on the site is still syncing.

## Webhooks

Subscribe to branch events with the `branches:read` scope:

* [`branch_created`](/data/v2.0.0-beta/reference/webhooks/webhooks/events/branch-created) — a new branch was created
* [`branch_merged`](/data/v2.0.0-beta/reference/webhooks/webhooks/events/branch-merged) — a branch was merged into main (the branch is auto-deleted; this does **not** also fire `branch_deleted`)
* [`branch_deleted`](/data/v2.0.0-beta/reference/webhooks/webhooks/events/branch-deleted) — a branch was explicitly deleted via the API

See [All Events](/data/v2.0.0-beta/reference/all-events) for the full webhook catalog and payload schemas.

## Related endpoints

* [List Branches](/data/v2.0.0-beta/reference/enterprise/branches/list)
* [Create Branch](/data/v2.0.0-beta/reference/enterprise/branches/create)
* [Merge Branch](/data/v2.0.0-beta/reference/enterprise/branches/merge)