Branches

The Branch API (beta) exposes page 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 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:

{
"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.

Branch lifecycle and status

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

StatusMeaningTypical nextActions
readyNo pending tasks, conflicts, or unpulled main changesmerge, publish, delete
needs_updateMain has changes the branch has not pulled in yetupdate, merge, publish, delete
has_conflictsStyle or component conflicts exist between branch and maincheck_conflicts, update, merge, publish, delete
updatingAn update-from-main task is queued or runningpoll_task
mergingA merge-into-main task is queued or runningpoll_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:

{
"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 until status is finished or failed. For create tasks, read branchId from the finished task response.

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 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 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):

{
"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:

{
"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 when one branch on the site is still syncing.

Webhooks

Subscribe to branch events with the branches:read scope:

  • branch_created — a new branch was created
  • branch_merged — a branch was merged into main (the branch is auto-deleted; this does not also fire branch_deleted)
  • branch_deleted — a branch was explicitly deleted via the API

See All Events for the full webhook catalog and payload schemas.