Delivery API vs management API responsibilities
Delivery API vs management API responsibilities
TL;DR
- Use the Content Delivery API (CDA) for all frontend/runtime content reads and the Content Management API (CMA) for back-office operations only.
- Separate your codebase into a content-read layer (CDA) and a content-admin layer (CMA), each with its own token lifecycle and failure policy.
- Choose the API by intent and data state, not by what returns results quickest during local development.
Most integration mistakes in headless projects are not caused by missing features. They are caused by blurry boundaries. This lesson exists to make one boundary unambiguous: the API used to deliver published content to experiences is not the API used to manage content operations.
In Contentstack terms, that means understanding when to use Content Delivery APIs (REST CDA or GraphQL CDA) versus the Content Management API (CMA), even though CMA also exposes GET operations. If you internalize this distinction early, you avoid a long list of production problems: token leaks, poor cache behavior, brittle frontend coupling, and unnecessary operational risk.
Why this boundary exists
Think in terms of system responsibilities:
- Delivery APIs are optimized for reading published content for runtime experiences.
- CMA is optimized for content operations: creating, updating, deleting, workflow-related actions, environment management, branch-level administration, and other control-plane tasks.
- CMA docs state that while CMA includes GET endpoints, teams should use Content Delivery API to deliver content to web/mobile properties.
- CDA docs emphasize CDA is for content retrieval and warn against using it for management-style activity.
That is not just documentation preference. It is architecture guidance: separate your delivery plane from your management plane.
The two APIs solve different reliability problems
A useful mental model is: these APIs solve different classes of reliability and security requirements.
Delivery API reliability profile
Delivery APIs are designed for high-volume read traffic and content delivery semantics:
- Environment-scoped delivery tokens
- CDN-backed retrieval behavior
- Query patterns designed for runtime reads
- Published-content focus
This aligns with frontend traffic patterns: many reads, low tolerance for latency spikes, predictable query contracts, aggressive caching where appropriate.
CMA reliability profile
CMA is designed for controlled mutation and administrative operations:
- Read-write capabilities
- Token models tied to management permissions (authtoken, management token, OAuth token)
- Operational endpoints beyond content retrieval
- Stronger coupling to governance and workflow state
This aligns with back-office traffic patterns: fewer requests, higher privilege, explicit auditability, stricter change control.
Trying to collapse both planes into one endpoint strategy usually creates a system that is neither secure enough for management nor efficient enough for delivery.
Decision framework: choose the API by intent, not convenience
Use this decision sequence when implementing any new integration:
- What is the intent of this call?
- Render user-facing experience with published content: CDA/GraphQL CDA.
- Manage content, schema, workflow, tokens, environments, branches, publishing actions: CMA.
- What data state do you need?
- Published runtime state: delivery plane.
- Draft/control-plane/administrative manipulation: management plane.
- Where does this call run?
- Browser or edge-rendered user route: never requires privileged management credentials.
- Trusted backend worker or orchestration service: may use CMA with least privilege.
- What token can safely exist in this runtime?
- Browser-safe read token for delivery use cases.
- Privileged management token only in trusted server context.
- What happens if this endpoint is abused?
- Delivery misuse typically impacts performance/cost.
- Management misuse can impact data integrity and security.
If your answers mix two intent classes in one path, split the design before writing code.
Architecture pattern that scales
A durable pattern is to create two explicit integration layers in your codebase:
- content-read layer: wraps CDA/GraphQL CDA and exposes domain read contracts for app teams.
- content-admin layer: wraps CMA for operational workflows, migrations, and automation jobs.
Each layer gets its own:
- token lifecycle
- observability
- rate/latency SLO expectations
- failure-handling policy
This prevents accidental privilege creep. It also lets teams evolve frontend frameworks without repeatedly touching CMS administration logic.
Worked scenario
Imagine product asks for a new “Related Articles” strip on article pages.
A common but flawed path is to let frontend developers use whichever endpoint gives quick access to references, including CMA reads, because “it works locally.”
A better path:
- Model and maintain references via CMA-backed tooling (if needed).
- Deliver runtime related entries through CDA/GraphQL CDA only.
- Expose a stable read contract to frontend teams (articleDetail + related[]).
- Track payload size and include depth as production metrics.
The result is cleaner ownership:
- editorial and model governance concerns stay in management workflows
- runtime rendering concerns stay in delivery contracts
Light implementation example
The point of the code below is not syntax. It is architectural separation by construction.
// api-clients.ts
export const deliveryClient = {
host: "https://cdn.contentstack.io",
headers: {
api_key: process.env.NEXT_PUBLIC_CONTENTSTACK_API_KEY!,
access_token: process.env.NEXT_PUBLIC_CONTENTSTACK_DELIVERY_TOKEN!,
},
};
export const managementClient = {
host: "https://api.contentstack.io",
headers: {
api_key: process.env.NEXT_PUBLIC_CONTENTSTACK_API_KEY!,
authorization: process.env.NEXT_PUBLIC_CONTENTSTACK_MANAGEMENT_TOKEN!,
},
};
// Rule: frontend request handlers can import deliveryClient only.
// CMA calls stay in trusted back-office services.Even simple module boundaries like this reduce accidental misuse dramatically.
Common failure modes (and prevention)
Common pitfall: Using CMA GET endpoints for frontend delivery seems to work locally but introduces token exposure risk, poor caching behavior, and audit confusion in production.
Failure mode 1: using CMA reads for frontend delivery
Why it happens: teams optimize for immediate convenience.
What breaks later: token exposure risk, weak caching behavior, mixed responsibilities, harder audits.
Prevention: lint/design rule that frontend runtime packages cannot import management clients.
Failure mode 2: treating all GET endpoints as equivalent
Why it happens: “GET means read, so it’s safe anywhere.”
What breaks later: governance and runtime concerns bleed into each other.
Prevention: classify endpoints by intent (delivery-plane vs management-plane), not HTTP verb.
Failure mode 3: token strategy designed after integration ships
Why it happens: security is deferred to “hardening phase.”
What breaks later: painful refactors, emergency rotations, uncertain blast radius.
Prevention: design token ownership and runtime placement before API contract implementation.
Failure mode 4: no contract boundary for frontend consumers
Why it happens: each team writes direct CMS queries inside feature code.
What breaks later: duplicated logic, inconsistent locale/branch handling, brittle migrations.
Prevention: centralized read contracts with versioning and observability.
Summary
If you remember one principle, keep this one: choose API by responsibility boundary, not by short-term implementation speed.
- Delivery APIs are your runtime content plane.
- CMA is your control plane.
When that separation is explicit in code, token policy, and team ownership, your system becomes easier to secure, easier to scale, and easier to change.