What headless Drupal with JSON:API involves
Headless Drupal means Drupal keeps the content model, editorial interface, workflows and permissions, while a separate front end renders the pages. The contract between them is the JSON:API module, which ships with Drupal core and exposes entities as resources over HTTP. Core REST is the alternative if your consumers need a custom resource shape or a format JSON:API does not fit. Either way, the API is the public product, so the first design decision is which entities and fields become part of it.
Teams usually choose this model for three reasons: the same content must reach several channels such as web, mobile and kiosks; a front-end team wants its own framework and release cadence; or the presentation layer must change without touching the content back end. Each reason has a cost. Drupal's entity structure tends to leak into the public contract, so field names and bundles that suit editors can become awkward for consumers. Plan a resource layer or a deliberate field naming scheme before the front end is built.
Three areas catch teams out. Access rules differ for anonymous and authenticated consumers, so confirm which roles can read unpublished content, which fields are hidden, and how the front end requests protected data. Preview for unpublished content needs its own route, token handling and a decision on who can see drafts. Cache invalidation across a CDN also needs a plan: confirm how Drupal cache tags map to CDN purge calls, because stale content is the most visible failure users will notice.
Confirm the platform baseline with your Drupal partner before scoping. This page assumes Drupal 11 on PHP 8.3 or later as the current major line. Drupal 10 reaches end of life on December 9, 2026, so a new build should not start on it. Check the PHP and web server versions in your own environment against the current Drupal requirements before you commit to a hosting design.
Components and settings involved
The exposed API surface is set by configuration and access rules rather than by installing a module. Each component below is a decision the team must make and record before the front end is built.
Core JSON:API resource paths
The core JSON:API module publishes every entity type and bundle as a resource under a path such as /jsonapi. The team must decide which entity types, bundles and collection routes are reachable by consumers and which are left out. Review the generated paths against the content model before any consumer depends on them.
Core REST module as an alternative
The core REST module exposes entities through plain resource routes and can be used where a consumer cannot follow the JSON:API specification. Enabling it alongside JSON:API doubles the surface that needs access review. Decide which module serves each consumer and disable the other where it is not needed.
Content types, fields and entity references
Each content type, field and entity reference becomes part of the API contract, so a field rename or a changed reference shape breaks consumers. Model content for the API before building the front end, and decide which fields are public, which are internal and how references are expanded in responses. Record the model as a versioned contract.
Field and entity access through roles
Anonymous and authenticated API requests are evaluated against Drupal role permissions, entity access and field-level access rules. A field hidden in the editor can still be exposed through the API if its access is not restricted. Test each role with real requests, including unpublished content and restricted fields, before go-live.
CORS and trusted host settings
Cross-origin requests from the front-end application depend on the CORS settings in the site configuration, and Drupal rejects requests whose host header does not match the trusted host patterns in settings.php. Both must list the exact front-end origins and the public API hostname. Misconfiguration often appears only in the browser or behind a reverse proxy, so test from each deployed origin.
Authentication layer for consumers
Consumers can authenticate with methods such as OAuth 2.0 through the Simple OAuth family of modules, session-based requests or other token schemes, depending on who calls the API. Decide which method each consumer uses, how tokens are issued and revoked, and which service accounts carry which roles. Confirm the chosen modules support your Drupal version before committing to them.
Front-end application and its build
The front-end application calls the API, renders content and owns its own routing, caching and build pipeline. The team must decide where it is hosted, how it learns about content changes and which fields it requests with sparse fieldsets or includes. Keep its request patterns in the same review as the Drupal permissions so both sides change together.
Decisions and trade-offs
This table compares the five decisions that shape a headless Drupal build, showing when each option fits and what it costs to run after launch.
| Decision | Option and when it fits | Operational cost |
|---|---|---|
| Public contract: JSON:API or core REST | JSON:API fits when the front end wants standard resource types, relationships, filtering and sparse fieldsets without custom endpoints. Core REST fits when you need a small set of bespoke responses and full control of the payload shape. | JSON:API gives a uniform URL structure that clients can learn once, but every entity type and bundle appears in the schema. Custom REST resources mean more code to write, test and document per endpoint. |
| Full headless or hybrid rendering | Full headless fits when the front end team owns all page rendering and Drupal serves content only. A hybrid fits when some pages, such as legacy landing pages or forms, still render in Drupal's theme layer. | Hybrid keeps two rendering paths, two caching strategies and two release processes to coordinate. Full headless moves SEO metadata, redirects and preview handling into the front end, which needs its own owners. |
| Public read-only or token-authenticated access | Public read-only fits published content that anyone can view. Token-authenticated access fits editorial previews, unpublished drafts and private content, where the front end must send credentials on each request. | Authenticated access adds token issuance, rotation, scope review and a secret store in each front-end environment. Caching of responses must also account for per-user visibility, which raises cache configuration effort. |
| Bare Drupal core or Drupal CMS | Bare Drupal core fits a content model designed around API consumers from the start, with no page builder in the critical path. Drupal CMS, a distribution with recipes and the Drupal Canvas page builder, fits teams whose pages are built inside Drupal, so it may add modules and config you do not need. | Starting from Drupal CMS can add front-end-oriented features that a headless design will not use, which means extra modules to audit and update. Bare core needs more upfront build effort for admin and editorial configuration. |
| Shared API gateway or direct to Drupal | A shared gateway fits organizations that already route APIs through a managed gateway and need central auth, rate limits and logging across several back ends. Direct access fits a single front end where Drupal's own caching and access control are sufficient. | A gateway adds a component to size, patch and monitor, plus route and policy configuration that must track each JSON:API change. Direct access keeps fewer moving parts but puts Drupal's endpoint surface and rate limiting directly on the public path. |
Build sequence
The steps below take a Drupal site from a content model to a documented, cached JSON:API that a decoupled front end can read safely from staging.
Define the content model from consumer needs
Start by listing the screens, components and channels the front end will render, then map each one to content types, fields and relationships. Content architects and the front-end lead do this together, before any editor-facing screens are tuned. The step closes when every consumer need traces to a named content type and field, and the team can explain why each field exists.
Classify entities and fields as public or internal
Mark each entity type, bundle and field as public (readable by the API) or internal (editorial, workflow or personal data). Security and content owners sign off on the list. The step closes with a written field inventory that the team can compare against the API responses in later checks.
Enable JSON:API and confirm resource paths
Enable the core JSON:API module, decide whether the core REST module is needed for any legacy consumer, and review the generated resource paths for each public bundle. Developers run the route list and a sample request against each path. The step closes when every public bundle returns a valid collection and a single-resource response in the staging environment.
Set role-based access and test both read paths
Configure the anonymous and authenticated roles so that only the public entities and fields are readable, and remove any permission that exposes unpublished content. The Drupal administrator and a tester then send requests as an anonymous client and as an authenticated user. The check passes when the anonymous request returns only published nodes and only public fields, and the authenticated request returns only what its role allows.
Add consumer authentication and token handling
Choose the authentication method for consumers, such as OAuth 2.0 bearer tokens, a module-based provider or a server-side proxy, based on who calls the API and where the secrets live. The developer implements token issuance, expiry and revocation, and the security team reviews storage on the front end. The step closes when a request with an expired or revoked token is rejected and a valid token reads the expected fields.
Configure CORS, trusted hosts and the preview path
Set cross-origin rules for each front-end origin, configure trusted host patterns in settings.php, and build a preview route that serves unpublished content only to authenticated editors. The team tests each origin from a browser and confirms that an unlisted origin is refused. The step closes when allowed origins succeed, a disallowed origin fails, and a preview request without editor credentials returns no draft content.
Set cache headers, cache tags and the edge layer
Confirm that JSON:API responses carry cache tags and sensible max-age and Vary headers, then place a CDN or reverse proxy in front of the API for anonymous reads. The performance engineer tests that a publish or edit invalidates the affected responses and that authenticated or preview traffic bypasses the shared cache. The step closes when an updated node appears on the edge within the purge behavior you have documented.
Connect the front end to staging and document the contract
Point the front-end framework at the staging endpoint, build the main templates against the real responses, and publish the contract for consumers: resource paths, fields, filters, authentication and error formats. The front-end and platform leads review the document together. The step closes when a clean build runs against staging and the contract matches the responses the anonymous and authenticated tests recorded.
Effort and cost drivers
This table lists the factors that make a headless Drupal build larger or smaller, how to keep each one contained, and what to ask for in a quote.
| Driver | Why it changes effort | How to keep it down |
|---|---|---|
| Content types and reference depth | Each content type adds fields, serializer behavior and JSON:API resource paths. Deep chains of entity references multiply the includes and cache tags a consumer must handle. | Model only the types consumers render. Limit reference depth to what a page needs and document the include parameters each endpoint supports. |
| Consumer applications and channels | Every front end, mobile app or partner feed needs its own review of field shape, access rules and error handling. Each new channel adds integration and testing time. | Agree a fixed set of consumers at discovery. Add channels through a written change request with its own scope and timeline. |
| Media and translation volume | Image styles, file derivatives, video handling and translated entities increase the number of URLs, cache entries and migration checks. Language fallback rules add test cases. | Define the image styles and file types the API exposes. Confirm which languages launch first and which content must be translated at launch. |
| Editorial preview and workflow | Preview of unpublished content from a decoupled front end needs a preview route, token handling and sometimes a separate build. Moderation states add permission rules that the API must respect. | Choose one preview method and one set of moderation states. Defer complex approval chains to a later phase if they are not required at launch. |
| Integrations that feed or read content | Each system that writes into Drupal or reads from it needs field mapping, error handling, retries and monitoring. Webhooks for cache invalidation or build triggers add more moving parts. | List every integration in the written scope with its direction, data volume and owner. Use one integration pattern for similar feeds. |
| Authentication methods and access rules | Public reads, authenticated writes and consumer-specific roles each need their own permission sets and tests. Mixing token types across consumers multiplies the review work. | Use one authentication method for writes and a small public read contract. Map roles from the identity provider once rather than per consumer. |
| Environments and deployment pipelines | Each environment needs configuration export, deployment steps, secrets and smoke tests. Separate pipelines for the Drupal back end and each front end add coordination work. | Keep environments to those the organization needs. Agree one release process that covers the back end and the front end together. |
| Compliance requirements for logs and access | Retention rules for API access logs, audit trails of content changes and evidence of access reviews add configuration, storage and reporting work. Requirements vary by sector and must be confirmed with the organization's compliance lead. | Confirm log retention and access review needs before design starts. Use the controls the organization already operates for its other platforms. |
| Cost components for a quote | Discovery and modeling time covers content and API design. Access and API work covers permissions, authentication and endpoint configuration. Front-end integration covers consumers. Ongoing schema maintenance covers changes after launch. | Ask for each component as a separate line in the written, fixed-scope quote. Ask which lines recur after launch and which are one-time build work. |
Access control and hardening for the API
Each control narrows what the API can return, accept or expose. Review them before the API receives any public traffic, and retest them after every configuration or module change.
Read access and field exposure
Create separate roles for anonymous and authenticated clients, and grant each role only the view permissions it needs for each content type. Confirm that JSON:API access and Drupal field-level access both hide unpublished content and internal fields such as editorial notes, draft revisions and author email addresses. Hiding a field in the front end does not stop the API from returning it, so test each role with a live request.
CORS origins for the front end
Allow cross-origin requests only from the front-end origins you list, and manage that list through your deployment configuration. Avoid wildcard origins on any endpoint that accepts credentials. Test from an origin that is not on the list to confirm the browser blocks the response. CORS governs what browsers let scripts read, so Drupal permissions remain the control for direct API calls.
Minimum write roles
Most headless front ends only read content, so grant create, update and delete permissions only where a documented workflow requires them. Assign those permissions to a dedicated integration account with the narrowest role that works, and limit it to specific entity types. Confirm which HTTP methods the JSON:API configuration accepts, and review the account's permissions after each change.
Client secrets and tokens
Keep client secrets and OAuth tokens on the server side, through a backend-for-frontend or secure build variables, so they never appear in a JavaScript bundle that browsers download. Search the compiled output and any published source maps for key-like strings. Agree on token lifetimes, refresh handling and secret rotation before launch.
Preview link protection
Preview links expose unpublished content, so they need their own controls: a time-limited or signed URL, a preview route that requires authentication, and a restricted front-end host. Confirm how your front-end framework validates preview requests and who can generate preview links. Test that an expired or copied link stops working.
Supported releases and module compatibility
The Drupal Security Team publishes advisories with CVE identifiers and risk scores, and security releases ship on the third Wednesday of the month, so assign someone to track them. Drupal 11 requires PHP 8.3 or later. Before choosing an authentication module, confirm which versions support your Drupal release. The SAML Authentication module's 8.x-3.14 release, for example, supports Drupal 10.3 and later and Drupal 11.
How to verify the result and failure behavior
Verify the API against a written contract before the front end depends on it. Keep a list of every JSON:API resource path the front end is allowed to call, with the expected fields for each content type and each role. Run schema and path checks against that list in the build pipeline, so a renamed field, a missing bundle or an unexpected new endpoint fails the build instead of reaching readers. The same list becomes the reference for reviewing changes made through Drupal's content type and field configuration.
Test access rules by sending the same request three ways: anonymously, as an authenticated editor and as an authenticated user with a restricted role. Compare the returned fields and entities with what the permissions and any entity access controls should allow. Add negative tests for content that should not appear: unpublished nodes, content from a revoked token, and requests from an origin that is not on the CORS allowlist in settings. A passing positive test does not prove the negative cases are blocked, so each one needs its own assertion.
Cache tests catch the failures that are hardest to see by hand. Publish an edit, confirm it appears through the API after the cache invalidates, and confirm that a response cached for one role is not returned to another. Check that the reverse proxy or CDN in front of Drupal respects the cache contexts and tags Drupal sends, including the Vary headers for authentication. Run load tests on the endpoints the front end calls most often, using realistic request mixes, and record the error rate and latency at the point where the site starts to degrade.
Failure behavior needs the same care. Errors from the API should give a clear status code and message without exposing stack traces, database details, internal entity IDs or file paths. Confirm this in the production-like environment with debug output off. The front end should render a defined fallback when the API is slow or unavailable, using a timeout that your team sets and tests. Finally, plan a rollback path for schema changes: keep configuration exported, test reverting the previous field and view configuration, and agree in advance who decides to roll back and how long that decision may take.
Operations after launch
This table lists what to monitor, back up, upgrade and document after a headless Drupal site goes live, with the failure point to watch for in each area.
| Area | What to set up | Where it usually goes wrong |
|---|---|---|
| Monitoring | Response times, error rates by JSON:API endpoint, cache hit ratios at the CDN or proxy, and authentication failures on the token endpoint. | Dashboards watch the homepage only, so a slow collection query or a failing token endpoint goes unnoticed. |
| Database and file backups | Back up the database and the file store together, from the same point in time, so media references in API responses stay valid. | Database and files are restored from different snapshots, leaving media entities pointing at missing files. |
| Configuration backup | Export the Drupal configuration on every release, store it in version control and keep it with the database backups. | Settings changed directly on production exist only on the live server and vanish during a rebuild. |
| Monthly bugfix releases | Apply bugfix releases from the first Wednesday of each month, tested in staging with the front-end build first. | Updates are skipped for months and then applied as one large change that no one has tested together. |
| Security releases | Apply security releases from the third Wednesday of the month, with a named owner and a same-week test window. | Security releases wait for the next planned window, leaving published advisories open on a public API. |
| Major version upgrades | Plan around the three-year major cadence. Drupal 12 is scheduled for the week of December 7, 2026, to confirm on the core release schedule. | Contributed modules and the front end are not tested against the new major version, and PHP 8.5 is not in place by the target date. |
| Public contract documentation | A versioned description of endpoints, fields, filters and includes that front-end teams build against. | Field renames or bundle changes ship without notice, and the front end breaks after an otherwise routine update. |
| Access matrix and token lifecycle | Which client or role can read or write each resource, plus rules for token issue, expiry, rotation and revocation. | Integration accounts keep broad roles and long-lived tokens after the application or staff member has changed. |
| Cache invalidation rules | Which content changes purge which CDN or proxy paths, and how Drupal cache tags map to JSON:API resources. | Stale content is served after publishing because purge rules cover only the homepage and list pages. |
Questions buyers ask
How much does a headless Drupal build cost?
The cost follows from the written scope, and DeployOpen does not publish a price list. The main components are discovery and content modeling, the Drupal build of content types, fields and API resource configuration, authentication integration with your identity provider, front-end integration with the consuming application, environment setup, testing, documentation and handover. Hosting, upgrades and maintenance recur after launch. Ask for a quote that lists each component, who performs it, which parts are one-time and which are ongoing support.
How long does a headless Drupal project take to deliver?
Duration depends on the content model, the number of consumers and the integrations involved. A small model with one front end and an existing identity provider takes less time than a model with several channels, multiple languages or integrations with back-end systems. Decision speed matters too, because content owners must settle modeling choices before endpoints are built. Ask for a schedule in the written scope with milestones and the assumptions behind each one. Timelines are agreed in writing before work starts.
Can our in-house team build a headless Drupal site alone?
Yes, if your team already has Drupal and front-end skills and time to learn the JSON:API and authentication details. The build needs Drupal site building and configuration, PHP work for custom modules and access control, familiarity with JSON:API or REST, caching and security configuration, and a front-end developer who can consume the API and handle authenticated requests. Your team also needs to own deployment, Drupal updates and monitoring after launch. Check these skills against the project plan before you decide.
What does a headless Drupal project need from our team?
The project needs three things from your side. Content owners make modeling decisions, such as which content types, fields and relationships the API exposes and which fields editors must always complete. A named front-end lead owns the consuming application, confirms the data it needs and signs off on response shapes. Access to staging and the identity provider includes test accounts and the configuration needed for sign-in. Agree who makes each decision and how quickly, and write those commitments into the scope.
Should we choose JSON:API or REST for Drupal?
It depends on what your consumers need and which tooling they already use. JSON:API follows a shared set of conventions for resource types, relationships, filtering, sparse fieldsets and included resources, which suits front ends that query related content. REST gives more direct control over endpoints and response shape, which can suit simple integrations or systems that expect custom payloads. Compare client libraries, caching behavior and your team's experience with each, then build a small prototype with representative content before committing.
Does Drupal licensing add cost to a headless build?
Drupal and the contributed projects hosted on Drupal.org are licensed under GPL-2.0-or-later, and there is no paid edition of Drupal itself, so there is no Drupal license fee. Costs still arise from hosting, PHP and Drupal version upgrades, contributed module maintenance, security monitoring and the build itself. Some supporting services, such as a hosted identity provider or a CDN, carry their own fees. Ask your provider which components are paid, who pays for each, and whether upgrades are included in any support retainer.
How DeployOpen scopes, builds and supports this work
DeployOpen plans, builds, hardens, documents and supports Drupal sites inside your own infrastructure, so the decoupled JSON:API back end, its authentication and its caching run where your governance already applies. The work starts with a written scope that defines the content model, endpoints and front-end consumers before any build begins.
How we scope
- The written scope lists the content types, fields, and entity relationships that JSON:API will expose to front-end consumers.
- Engagements are fixed-scope, so endpoints, consumers, authentication method and deliverables are agreed in writing before work starts.
- We confirm which JSON:API and REST resources are public, which require authentication, and which stay internal to the editorial team.
How we build
- We build the content model, JSON:API exposure, permissions and any contributed modules in a version-controlled Drupal codebase.
- Authentication for protected endpoints is configured and tested against the identity provider you specify, with role mapping defined in the scope.
- Caching, including cache metadata for API responses and any external cache or CDN layer, is configured and load tested against agreed traffic patterns.
How we hand over
- Handover includes the Composer-managed codebase, configuration export, deployment steps and environment settings for each stage.
- Documentation covers the endpoint catalog, field mappings, authentication setup, cache rules and the runbook for front-end teams.
- Automated tests for endpoints and permissions are delivered, and your team confirms the handover against the acceptance criteria in the scope.
How we support
- Ongoing support, upgrades and continuous testing are available as retainers, covering monthly bugfix and Wednesday security release windows.
- A retainer can cover JSON:API endpoint changes, contributed module compatibility checks and PHP and Drupal major version planning.
- Ask in your quote which Drupal release line the site targets and how upgrades to the next major version are scoped and priced.

