Guide
Storyblok Branches, and why they are not Git branches
The Branches app is now the Pipeline app. Here is what changed, what did not, and how to get branching on a plan that does not include it.
Last updated August 2026
If you are looking for Storyblok Branches and finding pages about Pipelines, you have not missed a deprecation. They are the same feature. Storyblok renamed the app, and the reason for the rename tells you most of what you need to know.
Why the rename happened
Storyblok’s explanation is that the name “Branches” created the wrong expectation — that these behave like Git branches. They do not, and the difference is not cosmetic.
| Git branches | Storyblok branches / pipeline stages | |
|---|---|---|
| Where you edit | Any branch | Preview only |
| Direction | Bidirectional — merge back | One-way, forward only |
| Merge conflicts | Expected, resolved by hand | Structurally impossible |
| Purpose | Parallel development | Sequential content staging |
A stage is not somewhere you work in parallel. It is a frozen destination you deploy into. Editors always work in Preview; everything downstream is read-only until a deployment pushes content forward.
The API kept the old name
This is where most confusion lands. The interface says Pipelines. The endpoint still says branches:
GET /v1/spaces/:space_id/branches
POST /v1/spaces/:space_id/branches
PUT /v1/spaces/:space_id/branches/:id
DELETE /v1/spaces/:space_id/branches/:idSo a codebase can legitimately have a file called branches.ts serving a page called Pipelines. That is Storyblok’s inconsistency, not yours.
What a branch object contains
{
"id": 12345,
"name": "Staging",
"space_id": 98765,
"source_id": 12344, // which branch this one syncs FROM
"url": "https://staging.site.com",
"position": 1,
"environment": "staging",
"deployed_at": "2026-07-30T09:12:44Z",
"deleted_at": null
}source_id is the important field: it defines lineage. null means the default Preview content. Everything else forms a chain rooted there.
Tokens select the branch
A delivery token can be bound to a branch_id. Your frontend then never names an environment — it holds one token, and that token is the environment. A deployment changes what the token returns without the site being redeployed or reconfigured.
POST /v1/spaces/:space_id/api_keys
{ "api_key": { "name": "Staging", "access": "public", "branch_id": 12345 } }The trap: ids are not stable
id changes across stages. Only its uuid is stable. Any code that carries an id across a stage boundary is wrong.This bites hardest on parent_id, relation fields and internal links, all of which are stage-local numeric references. Copy a story between stages without remapping them and you get content pointing at the wrong entry, or at nothing.
Branches are a paid add-on
The branches and deployments endpoints require the Pipelines app installed on the space. Without it, those routes are unavailable no matter how you call them — which is why so many teams end up duplicating spaces or copying stories by hand.
What stays open on every plan is /stories and /api_keys. That is enough to rebuild branching outside Storyblok, which is the approach Exacta takes: your space remains the only place anyone edits, and branches, promotion and per-branch tokens live on our side with the same API response shape.
Common questions
- Are Storyblok Branches deprecated?
- No. The Branches app was renamed to the Pipeline app. The feature is unchanged and the API resource is still called branches.
- Can I merge a Storyblok branch back into preview?
- No. Pipelines are one-way. Content flows forward from Preview into frozen stages; there is no merge back, which is why conflicts cannot occur.
- How do I point my site at a specific branch?
- Create a delivery token bound to that branch_id. The frontend holds that token permanently, and deployments change what it returns without any site change.
- Do I need a paid plan for Storyblok branches?
- The branches and deployments endpoints require the Pipelines app on the space. The stories and api_keys endpoints are available on every plan, which is what makes an external branching layer possible.
- How do I track the same story across branches?
- Use the uuid. Story ids are regenerated per stage, so uuid is the only identity that survives a branch boundary.