Headless CMS · invite-only early access

A headless CMS with room for every content type.

StackRoom is for teams who build their own front ends. Model content without counting types or entries, fetch a whole page in one request with references already expanded, and serve files from a CDN zone that belongs to your organization.

Moving from Contentful? Import your space directly.

Article article
7 fields
GET /api/delivery/v1/field-notes/production/entries/ent_7Qm2…
200 OK references expanded
{  "id": "ent_7Qm2Lx9Vb4Hc8Tn1Rw",  "modelApiId": "article",  "data": {    "title": "Twelve hours on the night ferry",    "slug": "night-ferry",    "author": {      "id": "ent_3Kd8Wq2Np6Ys1Fj9Lb",      "modelApiId": "author",      "data": { "name": "Inês Duarte", "role": "Contributing editor" },      "publishedAt": "2026-09-02T10:14:00.000Z",      "version": 2    },    "hero": {      "id": "ast_5Hv1Rz8Mc3Qe7Pk2Wd",      "url": "https://media.fieldnotes.example/ferry-deck.jpg",      "mimeType": "image/jpeg",      "width": 2400,      "height": 1600,      "alt": "Ferry deck at dusk, rope coiled by the rail"    },    "topics": [      {        "id": "ent_9Tb4Rk1Vx7Lm3Qa8Hs",        "modelApiId": "topic",        "data": { "name": "Slow travel" }      }    ],    "readingTime": 9,    "body": "<p>The boat leaves Piraeus at nine…</p>"  },  "publishedAt": "2026-10-19T07:30:00.000Z",  "version": 4,  "translations": {    "pt-BR": { "title": "Doze horas no ferry noturno" }  }}
Example project, synthetic data. Pick a field to find it in the response.
No cap
on content types or entries, on every plan, Free included
25
field kinds, from short text to taxonomy trees
1 request
per page: references and assets expand up to 10 levels deep
9
storage regions to choose from when you set up your organization
6×
webhook delivery attempts, spread over about 14 hours

01Content modeling

Model what you publish, not what your plan allows.

When content types are rationed, teams cram a landing page, a press release and an FAQ into one generic "page" type and sort it out in code. StackRoom has no limit on content types or entries, so every kind of content gets a type of its own.

25 field kinds
Text, numbers and dates, media, references, taxonomy trees, JSON and code, plus presets such as slug, email, currency and color.
Validation the API enforces
Required fields, length and number ranges, and patterns for slugs, emails and URLs. An entry that breaks a rule can't be published.
Environments to try things in
New projects start with production and staging. Each environment keeps its own models, so a schema change can wait in staging.
Add a field

Text

  • Short textTitles, names, single line
  • Long textPlain multi-line text
  • Rich textFormatted text, embeds, links
  • MarkdownPlain text with markdown
  • EnumerationA fixed list of allowed values

Number & date

  • NumberInteger or decimal
  • DateDate, or date & time with a time zone
  • BooleanTrue / false toggle

Media

  • AssetImage, video or any file
  • Asset galleryMultiple images, videos or files
  • FileA downloadable document
  • Video embedYouTube / Vimeo embed

Relationships

  • ReferenceLink a single entry
  • Reference (many)Link multiple entries
  • TaxonomyA tree of reusable terms

Presets

  • SlugURL-safe, auto from a field
  • EmailValidated email address
  • URLValidated web address
  • PhonePhone number
  • CurrencyMoney with a symbol
  • PercentageA 0–100 value
  • RatingA star rating
  • ColorA color swatch + hex

Advanced

  • JSON objectRaw structured data
  • CodeA formatted code snippet

AI schema assistant Paid plans

Or describe the type and review what it proposes.

Write a sentence, paste a URL or drop in a screenshot. The assistant proposes fields and groups, and only ever adds: it never edits or removes what's already there, and nothing is saved until you press Save.

A café location: its name, the address, opening hours for each day, a phone number and some photos.
  • Name name Short textRequired
  • Address address Long text
  • Opening hours openingHours JSON object
  • Phone phone Phone
  • Photos photos Asset gallery
5 fields to add · 0 changed Add to schema

Illustrative proposal.

02Delivery API

One request returns the whole page.

A plain REST API that returns JSON. Linked entries and assets come back inline, so a page with an author, a hero image and related posts is one call, not a chain of follow-up requests.

Read the Delivery API reference

/api/delivery/v1/{project}/{environment}

  • GET /entries List, filter and sort entries
  • GET /entries/{id} One entry, references expanded
  • GET /models Every content model
  • GET /models/{id} One model and its fields
  • GET /assets List assets
  • GET /assets/{id} One asset
  • POST /entries/{id}/events Record an A/B view or conversion
Filter and sort by your own fieldscURL
BASE=https://app.stackroom.co/api/delivery/v1

curl -G "$BASE/field-notes/production/entries" \
  -H "Authorization: Bearer $STACKROOM_API_KEY" \
  -d model=article \
  -d "fields.title[match]=ferry" \
  -d "fields.readingTime[lte]=10" \
  -d order=-publishedAt -d limit=12
Response200 OK
{
  "entries": [
    { "id": "ent_7Qm2Lx9Vb4Hc8Tn1Rw", "modelApiId": "article",
      "data": { "title": "Twelve hours on the night ferry",
                "author": { "data": { "name": "Inês Duarte" } … },
                "readingTime": 9, … },
      "version": 4 }
  ],
  "total": 1, "limit": 12, "offset": 0
}

Example request against a synthetic project. Response shortened with “…”.

Filters on any field
fields.{apiId}[op]= with eq · ne · in · nin · lt · lte · gt · gte · match · prefix · empty · notEmpty, and has · hasNot · hasAny · hasAll · empty · notEmpty for list fields. Sort with order=-fields.{apiId}. Filtering guide
Delivery and preview keys
A delivery key (sk_dlv_…) reads only what's published. A preview key (sk_prv_…) also returns drafts, for preview builds. Keys can be limited to particular projects and environments.
Translations without duplicates
data is always the default locale. Localized fields add a translations object that holds only the overrides, so every other locale falls back to the default.
No SDK to install
Bearer-token auth over HTTPS, so fetch or any HTTP client in any language works. Each key can make 300 requests a minute, and errors come back as JSON with a message.

03Editing and publishing

Editors change things without changing the live site.

A published entry keeps serving while someone edits it. Changes go live when they press Publish, and any earlier published version is one click from coming back.

  1. Draft

    Saved as you type. Not on the Delivery API yet.

  2. Published

    Live for delivery keys, with a version number to cache on.

  3. Changed

    Edits wait here while the published version keeps serving.

  4. Archived

    Out of the API, kept in the space, restorable.

Version history you can restore

Every publish, unpublish, archive, discard and restore records a version. Compare one with the current entry, then restore any published version. Restoring publishes it again.

Current Title, BodyDraft changes Changed
v4 PublishedInês D. · Oct 19 Live
v3 PublishedTomás R. · Oct 12 Restore
v2 Back to draftInês D. · Oct 11
v1 PublishedInês D. · Oct 9 Restore

Translate only what changes

Mark a field as localized and each locale stores just its overrides. Untranslated fields fall back to the default locale instead of being copied into every language.

Title Doze horas no ferry noturno Override
Body The boat leaves Piraeus at nine… From en-US
Reading time 9 Not localized

Roles for the whole team

Invite people into the organization with one of five roles, from read-only to owner.

  1. 1Viewer
  2. 2Author
  3. 3Editor
  4. 4Admin
  5. 5Owner

See what links to an entry

Each entry and asset has a References tab that maps what links to it and what it links to, so you know what a change touches before you archive anything.

04Assets and CDN

Your files, on a CDN zone of your own.

Each organization gets its own Bunny storage zone and pull zone, not a slot on a shared bucket. You pick where files are stored, which regions serve them and which domain they're served from.

https://media.fieldnotes.example/en-US/1760857800000-ferry-deck.jpg?width=960&format=auto

  1. Your hostname Add a custom domain in Settings. StackRoom attaches it to your pull zone and issues a free TLS certificate.
  2. A key per published file A replacement file waits as a pending change. Publishing gives it a new URL, so caches never serve a stale image under the old one.
  3. Transforms on request Pass width, height, format (webp, avif or auto) and quality to the Delivery API and asset URLs come back resized.
Anatomy of an asset URL in a Delivery API response. Example domain.

Storage region

One main region, chosen when you set up the organization, plus optional geo-replication.

  • Frankfurt · main
  • London
  • Stockholm
  • Los Angeles
  • New York
  • Singapore
  • Sydney
  • São Paulo
  • Johannesburg

Delivery zones

Turn on the parts of the world your audience is in.

  • Europe
  • North America
  • Asia & Oceania
  • Middle East & Africa
  • South America

Assets publish like entries

Replace a file or edit alt text, and the change waits until you publish it. Archive an asset to take it out of the API without deleting it. Each locale can have its own file and alt text.

Bandwidth you can see

Storage, bandwidth and API requests are tracked per organization, with a daily bandwidth chart.

05Experiments and webhooks

Test a headline. Rebuild on publish.

A/B testing

Variants live on the entry, not in another tool.

Override any fields for a variant, set the split, and the Delivery API returns the variants with their weights. Your front end picks an arm per visitor and posts views and conversions back. StackRoom reports the rates and uplift, and you declare the winner.

A/B testing guide
Experiment Running
ArmVisitorsConversionUplift
Control 50% Twelve hours on the night ferry 2,1404.5%—
Variant B 50%Leading The slow way to Crete 2,0955.8%+29%

Last 30 days. Illustrative numbers.

Webhooks

Tell your build when content goes live.

Subscribe to entry.publish, entry.draft and entry.archive for a project, an environment and the content types you choose. Each delivery carries the full entry, references expanded, like a Delivery API read.

POST https://build.fieldnotes.example/hooks/stackroom
X-Stackroom-Secret: whsec_…

{ "type": "entry.publish",
  "project": "field-notes", "environment": "production",
  "entry": { "id": "ent_7Qm2…", "version": 4, … } }

If your endpoint fails, StackRoom keeps trying: 6 attempts over about 14 hours.

  1. first
  2. +1 min
  3. +5 min
  4. +30 min
  5. +2 h
  6. +12 h

A webhook pauses itself after 10 failed deliveries in a row. Every delivery is logged and can be sent again.

06Migrate from Contentful

Bring your Contentful space with you.

The importer reads your content types, entries, assets and locales from Contentful and recreates them in StackRoom. Rich text becomes HTML, asset files are copied to your own CDN zone, and references are linked up once every entry exists.

  1. 1

    Connect

    Paste a Contentful personal access token, from Settings → API keys → Content management tokens.

  2. 2

    Pick the source

    Choose the Contentful space and environment to bring across.

  3. 3

    Review the mapping

    See how many content types, entries and assets will move, and every field that cannot map one to one.

  4. 4

    Import

    The import runs in the background with progress, into the StackRoom environment you started it from.

No silent losses. Fields that change shape are flagged in the preview before anything is imported, for example:

  • LocationImported as raw JSON, { lat, lon }
  • Object (no declared structure)Imported as raw JSON
  • List limited to fixed valuesImported as a plain text list, without that limit

Starting fresh instead?

  1. 01 Request a demo Tell us what you are building. StackRoom is invite-only during early access.
  2. 02 Set up your organization Pick the storage region, replication and delivery zones. Your CDN zone is created for you.
  3. 03 Model, publish, fetch Create content types, invite your editors, and create an API key for your front end.
Request a demo

07Pricing

Limits on usage, never on your model.

No plan counts content types or entries. Plans differ in projects, seats, requests, storage and bandwidth, plus three features that are on paid plans only.

Free

$0 / month

For one site or app, with its production and staging environments.

Content types
Unlimited
Entries
Unlimited
Projects
1
Environments per project
2
Team members
2
API keys
2
API requests
100,000 / month
Asset storage
2 GB
CDN bandwidth
10 GB / month
Request a demo

08Questions

Before you ask.

Something else? Email brendon@stackroom.co, or read the API docs.

Can I sign up today?

StackRoom is invite-only during early access. Request a demo and tell us what you are building. If it is a fit, you get an invitation and set up your organization from there.

What does “no limit on content types” mean exactly?

No plan, Free included, caps how many content types or entries you create. Plans limit projects, environments, team members, API keys, monthly API requests, asset storage and CDN bandwidth instead.

Is there a GraphQL API or an SDK?

Not today. The Delivery API is REST over HTTPS with JSON responses and bearer-token auth, so fetch or any HTTP client works. References and assets come back expanded, which covers most of what people reach for GraphQL to do. Each key can make 300 requests a minute.

How do previews of unpublished content work?

Create a preview key and use it where you build previews. It returns drafts and pending changes as well as published content, while delivery keys only ever see what is published.

What comes across from Contentful, and what doesn’t?

Content types, entries, assets and locales. Rich text is converted to HTML and asset files are copied into your CDN zone. Fields that can’t map one to one, such as Location or untyped Object fields, are imported as JSON and flagged in the preview before you start, so you can decide first.

Where are our files stored?

In a Bunny storage zone created for your organization, in the main region you choose at setup, with optional geo-replication. Files are served from your own pull zone, on a custom domain with a free TLS certificate if you add one.

Who on our team can do what?

There are five roles: viewer, author, editor, admin and owner. Admins and owners manage settings such as API keys, webhooks, domains and members.

Give every kind of content a type of its own.

Tell us what you're building and we'll walk you through StackRoom with your own content model in mind.