When a Feature Is Gated

You are most likely reading this because something is missing: a panel that says you need a different plan, a button that is not there, a recommendation block that renders nothing, or a search box on your published site that returns no results at all. A plan gate is not a permission problem, and Leed does not gate everything the same way — which is why “nothing happened” is sometimes the correct gated behavior rather than a fault.

This page describes the five things a gate can actually look like, the error that sits behind the visible ones, and the handful of gates that are deliberately silent.

Plan gates are not permission errors

Two different systems can stop you, and they have different fixes and different people to ask.

PermissionPlan gate
The question it answersWho are you? Your role and any overrides on this resourceWhat does this workspace pay for?
HTTP status403402
Who fixes itSomeone with the Administrator role, on Settings → TeamSomeone who holds billing access, on Settings → Plans & billing
Applies toOne personEveryone in the workspace

The two are additive: a plan gate never grants access, and a role never buys a feature. If you can see a surface but it refuses to save, check which of the two you are looking at before asking for the wrong thing. Roles and permissions covers the role side, and billing and developer access covers who in your workspace is allowed to change the plan at all.

The upgrade prompt

Every gated surface in the CMS renders the same component, so the prompt looks and reads the same wherever you meet it. It comes in three shapes:

  • a panel that replaces the surface entirely — the whole screen becomes the prompt;
  • a banner above or inside a surface that otherwise still works, used where part of a screen is gated and the rest is not;
  • a coming soon variant, reserved for capabilities that are gated and not built yet, which reads “is coming soon” and “Arriving on theplan.”
The campaign planner replaced by a full-panel upgrade prompt on a Free workspace

The copy is generated from the feature and the plan it needs, so it is always specific:

Campaign planner is available on the Growth plan Upgrade to the Growth plan to unlock campaign planner for your team.

What sits under that sentence depends on whether you can act on it:

  • If you hold billing access, you get an Upgrade plan button that goes to Settings → Plans & billing.
  • If you do not, you get the plain sentence “Ask your account admin to upgrade your plan.” and no button.
The same gated surface for a member without billing access, showing the ask-your-admin line instead of a button

Nothing vanishes from the interface because of your plan. Rail tabs, settings cards and menu entries render the same on Free as on Enterprise; it is the destination that renders the upgrade state when you arrive. So a section you cannot use is still discoverable, and the prompt inside it tells you what it costs.

The one thing your plan does hide is the Billing & plan settings card itself — and that is a permission, not a plan gate. It is hidden from people without billing access on every tier, Enterprise included.

The error behind the prompt

Behind every visible gate is one JSON body, shared by feature gates, quota checks and the analytics window alike. If you are reading the network tab, scripting against the API or debugging an MCP client, this is the shape to match on.

{
  "error": "upgrade_required",
  "reason": "feature_gated",
  "feature": "campaignPlanner",
  "requiredTier": "growth",
  "currentTier": "free"
}

A quota refusal carries the same envelope with a different reason and two extra numbers. Here, a Free workspace asked for analytics reaching 90 days back against a 30-day window:

{
  "error": "upgrade_required",
  "reason": "quota_exceeded",
  "feature": "analyticsRetention",
  "currentTier": "free",
  "quota": 30,
  "used": 90
}
FieldAlways present?Meaning
errorYesAlways the literal string upgrade_required
reasonYesfeature_gated (the plan does not include this capability) or quota_exceeded (it does, and you have used it up)
featureYesA capability name such as campaignPlanner — or, on a quota denial, a quota kind: contacts or analyticsRetention
requiredTierOn feature_gated; optional on quota_exceededThe lowest plan that includes it
currentTierYesThe workspace’s plan right now
quotaOn quota_exceeded onlyYour allowance — a count, or a number of days for retention
usedOn quota_exceeded onlyWhat you used, or how far back you asked

Note that feature on a quota denial is not a plan feature. contacts and analyticsRetention ride this body because it is the one shape every denial emits, but they are meters rather than capabilities — usage and limits covers all three of them, including the marketing-email allowance.

A 400 is not a gate

One error is reliably misread as a plan gate and is not one. When you set a custom documentation theme, code theme or font name, the bare name must match ^[a-z0-9]{1,32}$ — lowercase letters and digits only, no dashes, at most 32 characters. A malformed name is a 400 with the message “a custom name must be lowercase letters and numbers only, at most 32 characters”, and it is a 400 on every plan, Enterprise included, because the shape is checked before the plan is consulted at all.

So leedai is accepted and leed-ai is rejected, and the rejection has nothing to do with what you pay. There is a plan gate on the same field — naming a custom theme is a Starter capability — but it fires only when you introduce a new custom value. Re-sending the value you already have, clearing it, or switching between built-in themes passes on every tier, which is why a downgraded workspace can still open Settings without being refused. The naming rules themselves live with custom documentation themes.

The five ways a gate can behave

Under the hood there are nine distinct enforcement points. What a person can actually observe collapses to five, and knowing which one you are looking at is the difference between “I need a bigger plan” and “this product is broken”.

flowchart TD
    A[You do something] --> R{Does your role<br/>allow it?}
    R -->|No| F403[403 — permission denied<br/>Ask an administrator]
    R -->|Yes| P{Does your plan<br/>include it?}
    P -->|Yes| OK[It works]
    P -->|No| K{Where are you?}
    K -->|A CMS screen| B1[Upgrade prompt<br/>e.g. campaign planner, short links]
    K -->|A CMS editor control| B2[Hidden control<br/>e.g. site layouts, email templates]
    K -->|A record you can read| B3[Withheld data<br/>e.g. transcripts, reader history]
    K -->|Your published site| B4[Empty result or 404<br/>e.g. recommendations, live search]
    K -->|Your site build| B5[Skipped at build<br/>e.g. auto-linking, footer badge]
What you seeWhere it happensReal examplesWhat to do
Upgrade promptCMS screensCampaign planner, dynamic CTAs, short links, recommendation settings, gated analytics metrics, sending a marketing emailRead the plan it names; upgrade, or send that sentence to whoever holds billing access
Hidden controlCMS editorsCustom theme and font name fields, site layouts, email templatesNothing is broken — the editing UI is not rendered below its plan
Withheld dataA record that still loadsTranscripts and extracted document text, per-reader history on a contact profileThe record is intact and stored; only part of the response is removed
Empty or not foundYour published site’s endpointsRecommendations return 200 [], dynamic CTA slots return 200 {}, live documentation search returns 404Expected below the plan — a visitor must never see a billing error
Skipped at buildYour site buildAuto-linking, the live-search client, the “Powered by Leed” footer badgeThe site builds successfully without the feature; it appears at the next build after an upgrade

Which capability sits behind which behavior is listed feature by feature in feature availability by plan.

You get a prompt or you get nothing rendered. Gated screens replace themselves with the upgrade panel, gated sub-sections carry a banner, and gated editing controls are simply absent. Reads are almost never gated — a downgraded workspace can still see its own data, which is what makes cleaning up after a downgrade possible.

For developers: which routes gate, and which stay open below the gate

Gates are placed on writes, not on reads, and specifically so that a workspace that drops a plan can still tidy up after itself.

SurfaceBlocked below its planStill allowed on every plan
Distribution channels (page Workflows)Creating a channel, enabling one, or changing its configurationReading them, switching one off, and deleting one — a plain {"enabled": false} update is never gated
Content-level access overridesCreating a page-type or label overrideExisting overrides keep working; per-page and contact overrides are ungated; deleting an override always works
Custom theme and font namesIntroducing a new custom valueEchoing back the stored value, clearing it, and switching between built-in themes
Campaign plannerEvery /campaigns routeThe plan calendar is deliberately left ungated, so the calendar view keeps working
AssetsNothing — upload, transcription and extraction run on every tierThe whole pipeline; only the transcript and extracted text are stripped from the response below Starter

An unknown identifier is resolved before the plan is consulted, so asking about something that does not exist returns 404 rather than leaking a 402 about a resource you cannot see.

Gates you will not see at all

The silent set deserves naming, because a quiet gate is the one that makes people think Leed is broken.

  • Recommendations return an empty list on your published site. The recommendation block renders nothing at all.
  • Dynamic CTAs return an empty payload, so the CTA slot stays blank.
  • Live documentation search returns 404 — at the edge and at the API — so it reads as “there is no search here” rather than as a payment error. This is deliberate: a visitor’s browser must never receive a billing error from your site.
  • Transcripts and extracted document text are stripped out of the asset response while the “a transcript exists” flag survives. That is why an asset page can honestly tell you a transcript is there and still not show it to you.
  • Per-reader history is withheld from a contact’s profile while the profile itself loads normally. Identified contacts are a Free capability; their per-reader timeline is not.
  • Auto-linking is skipped when your site builds. The build succeeds and says nothing in the foreground.
  • An ejectable documentation header or footer is not offered. Both templates require Starter, and leed site eject neither lists nor ejects a template above your plan — a developer meets an absence, not a refusal. The eject command explains what the list contains.

One surface breaks the rule that every gated CMS screen renders a prompt: the click-count overlay in the page editor refuses below Growth and renders nothing at all — no panel, no banner, no explanation. That is a known defect rather than intended design, and it is recorded in known limitations.

A gentler example of the same mixed state is the editor’s Workflows tab, where a locked channel stays visible with its plan named in the row’s detail text, next to channels you can use:

The page editor's Workflows tab on a Starter workspace, with a social channel row locked and labeled Growth plan

A locked channel that is already switched on can still be switched off. That is deliberate — see page workflows.

If you cannot upgrade

Most people who hit a gate cannot buy their way past it, because billing access is held by one or two people in a workspace.

Whoever holds billing access goes to Settings → Plans & billing, where the plan chooser and checkout live — managing your subscription walks through the screen, and plans and tiers is the shorter argument for what each rung buys. Administrators have that access already; anyone else needs the billing override, which an Administrator grants per person on Settings → Team, as described in billing and developer access.

ESC