Video Production Plan : Video 5 — API Architecture, Authentication, and Query Surface Choice
Video 5 — API Architecture, Authentication, and Query Surface Choice
| Attribute | Details |
|---|---|
| Course | 3 (APIs and Developer Tooling), Module 3.1 |
| Covers | Lessons 3.1.1, 3.1.2, 3.1.3, 3.1.4, 3.1.5 |
| Priority | Critical |
| Length | 18-25 min |
| Format | Screencast (Postman/terminal + slides for architecture diagrams) |
| Status | Not started |
Why This Video Matters
This clarifies the boundaries developers most often confuse. Most API mistakes are boundary mistakes, not syntax mistakes.
Outline
- Two APIs, two jobs: Delivery API (read-only, CDN-backed, fast) vs Management API (CRUD, authenticated, for tooling)
- When to use which: frontend always uses Delivery; CI/CD, migrations, and admin scripts use Management
- Preview vs published delivery concerns
- Regions and clouds: NA, EU, Azure NA, Azure EU — each has different base URLs
- Show where to find the correct base URL for your stack
- REST vs GraphQL tradeoffs: REST for simple queries and full SDK support; GraphQL for precise field selection and reducing over-fetching
- Show the same query in REST and GraphQL side-by-side, compare payload sizes
- Authentication: Delivery Tokens (environment-scoped, read-only) vs Management Tokens vs OAuth
- Token placement and credential scoping — demonstrate creating and using each token type
- Rate limits: know the limits, handle 429 responses gracefully, implement backoff
- Error codes walkthrough: common errors (401, 404, 422, 429) and what to do about each
Key Lines
"Most API mistakes are boundary mistakes, not syntax mistakes."
"Choose the API by intent, not by convenience."
"If a token ends up in the wrong runtime, that is an architecture issue, not a documentation issue."
Detailed Talking Points
1. Two APIs, two jobs
- Contentstack has two separate API planes: the Content Delivery API (CDA) and the Content Management API (CMA). They exist for fundamentally different reasons.
- CDA is read-only, CDN-backed, optimized for high-volume frontend traffic. It only returns published content.
- CMA handles CRUD operations: creating entries, updating content types, managing workflows, publishing, branch administration.
- These are two different reliability planes. CDA is designed for many reads, low latency, aggressive caching. CMA is designed for fewer requests, higher privilege, explicit auditability.
- Different token types protect each plane. Delivery tokens are environment-scoped and read-only. Management tokens are stack-level and read-write.
- Different blast radius: if a delivery token leaks, an attacker can read published content. If a management token leaks, an attacker can modify or delete your entire stack.
- Think of it as: delivery plane vs control plane. Keep them separated in your codebase, your token strategy, and your mental model.
2. When to use which: the decision framework
- Do not choose the API by convenience or by what returns results during local dev. Choose by intent.
- Five-question decision sequence: (1) What is the intent -- render or manage? (2) What data state -- published or draft? (3) Where does this call run -- browser/edge or backend? (4) What token can safely exist in this runtime? (5) What happens if this endpoint is abused?
- If the intent is rendering published content for users: CDA. Always.
- If the intent is content operations -- creating, updating, deleting, publishing, workflow actions: CMA. Only in trusted backends.
- If your answers to these five questions mix two intent classes in one code path, split the design before writing code.
- CMA has GET endpoints. That does not make them delivery endpoints. Classify by intent, not HTTP verb.
- Common mistake: using CMA reads in frontend code because "it works locally." It does work -- until you ship a management token to the browser.
3. Preview vs published delivery concerns
- CDA returns only published content for a given environment. If an editor saves a draft, CDA will not reflect it.
- For draft or preview content, use the Preview API with preview tokens -- a separate retrieval context.
- Preview tokens are still read-path credentials. They should never grant management capabilities.
- In Veda's case: the storefront uses CDA for production traffic. The editorial preview experience uses the Preview API so editors see unpublished changes.
4. Regions and clouds
- Your stack's region is locked at creation. It determines every API base URL your code targets. You cannot change it later.
- Contentstack operates across seven regions on three cloud providers: AWS (NA, EU, AU), Azure (NA, EU), GCP (NA, EU).
- Each region has its own set of base URLs for CDA, CMA, GraphQL, Preview, Assets, and all platform services.
- AWS NA is the "default" -- it uses the .io TLD (cdn.contentstack.io). Every other region uses .com with a prefix (eu-cdn.contentstack.com, azure-na-cdn.contentstack.com).
- The .io vs .com TLD difference is a common copy-paste error. If you switch from NA to EU and only change the prefix but keep .io, your requests will fail silently.
- Reasons for region choice: data residency (GDPR), latency, cloud provider alignment with existing infrastructure.
5. Finding the correct base URL
- Dashboard: Settings > Stack shows the region.
- Browser URL gives a hint: eu-app.contentstack.com means AWS EU, azure-na-app.contentstack.com means Azure NA.
- Use the SDK's built-in region constants (Contentstack.Region.EU, Contentstack.Region.AZURE_NA, etc.) -- the SDK constructs correct endpoints automatically.
- For endpoints beyond the Delivery SDK (Preview host, Application host for Live Preview), use the @timbenniks/contentstack-endpoints package or reference the official regions data at artifacts.contentstack.com/regions.json.
- Quick diagnostic: if credentials are correct but you get 401 or empty results, test the same request with curl against different region base URLs. One returns 200, the other returns 401. The 200 one is your actual region.
6. REST vs GraphQL tradeoffs
- Both REST CDA and GraphQL CDA are read-only, use the same delivery tokens, return only published content, and sit behind CDN infrastructure.
- REST strengths: simple and predictable URLs, strong CDN caching (GET requests are inherently cacheable), mature SDK support, include[] for reference resolution, rich query operators ($in, $gt, $regex, etc.).
- REST limitation: over-fetching. You get all fields even if you only need two. Fixed response shape. Multiple round trips for unrelated content types.
- GraphQL strengths: request exactly the fields you need, fetch from multiple content types in a single query, schema introspection, type safety with codegen.
- GraphQL limitations: no mutations (all writes go through REST CMA), query complexity limits for deeply nested references, POST-based requests are harder to cache at CDN edge, SDK support is primarily REST-oriented.
- GraphQL does not support the SDK include[] syntax for references. It uses the Relay-style Connection pattern instead.
- Neither is "better." Choose per-query based on actual needs: payload size sensitivity, query complexity, caching requirements, team familiarity.
7. Same query in REST and GraphQL side-by-side
- Show fetching blog posts with author references in REST: GET /v3/content_types/blog_post/entries?environment=production&include[]=author with api_key and access_token headers.
- Show the same query in GraphQL: a query selecting only title, url, and authorConnection with specific fields.
- Compare the response payloads. REST returns every field on blog_post and author. GraphQL returns exactly what you asked for.
- Point out the Connection syntax in GraphQL for references and assets -- this is Contentstack-specific and catches people off guard.
- Call out that both use the same delivery token. The auth model is identical. The query model is different.
8. Authentication: token types and their roles
- Three credential types to know: Delivery Tokens, Management Tokens, and OAuth tokens.
- Delivery Tokens: environment-scoped, read-only, safe for client-side code. They can only read published content for one specific environment.
- Management Tokens: stack-level, read-write, never expose to clients. They can create, update, delete entries, modify content types, manage workflows. If this token leaks, your stack is compromised.
- OAuth: used for Contentstack Apps. Enables user-context-aware operations with consent flows.
- Design your credential model around four questions: Who is the actor? What plane is accessed? What is the minimum scope? How will this credential be rotated?
- Token selection should be the output of this security model, not the starting point.
9. Token placement and credential scoping
- Show creating a delivery token in the dashboard: Settings > Tokens > Delivery Tokens. Note it is scoped to a specific environment.
- Show creating a management token: Settings > Tokens > Management Tokens. Note the stack-level scope and permission configuration.
- Code example: separate deliveryClient and managementClient configs in api-clients.ts. The delivery client uses cdn.contentstack.io with access_token. The management client uses api.contentstack.io with authorization.
- Architectural rule: frontend request handlers can import deliveryClient only. CMA calls stay in trusted back-office services. Enforce this with linter rules or module boundaries.
- Smell test: if revoking one token would break many unrelated systems, your security boundary is too broad. One credential per service responsibility.
10. Rate limits: know them, respect them, handle 429
- CDA rate limits are generous (paid plans: ~200 req/s) because delivery traffic is cacheable and read-only.
- CMA rate limits are tighter (~10 req/s default) because it handles write operations. This is where rate limiting becomes a daily concern during migrations, bulk publishes, and automated workflows.
- Read X-RateLimit-Remaining on every response -- not just errors. Proactively throttle before hitting the wall.
- When you get a 429: exponential backoff with jitter. Formula: delay = min(baseDelay * 2^attempt + random(0, jitterMax), maxDelay).
- Jitter is not optional. Without it, concurrent clients synchronize their retries and create a thundering herd -- all retrying at the same instant, re-triggering the overload.
- CMA write retries have an idempotency danger: if a POST times out but the server processed it, retrying creates a duplicate entry. Use UID-based updates when possible, or check for existence before retrying creates.
11. Error codes walkthrough
- 401 Unauthorized: wrong or missing token. Could also mean correct token but wrong region endpoint. Do not retry -- fix the credential or region.
- 404 Not Found: wrong content type UID, wrong entry UID, or malformed API path. Could also mean correct UID but wrong region. One edge case: brief 404 right after publishing due to propagation delay.
- 412 Precondition Failed: version conflict on CMA entry update, or region/credential mismatch. For version conflicts: re-fetch the entry, get the current version, merge your changes, resubmit.
- 422 Unprocessable Entity: your JSON is syntactically valid but semantically wrong. Missing required fields, invalid reference UIDs, validation rule violations. Do not retry -- fix the payload.
- 429 Too Many Requests: rate limited. Retry with exponential backoff + jitter.
- Classify before retrying. 429 and 500 are retryable. 401, 403, 404, and 422 are permanent. 412 is retryable but requires a re-fetch first. Retrying permanent errors wastes rate limit quota with zero chance of success.
Screen: What to Show
| Outline item | Screen instructions |
|---|---|
| Opening (Outline items 1-3) |
Slide: architecture diagram showing two planes side-by-side. Left: "Delivery Plane" (CDA, GraphQL CDA, Preview API) with arrows to browser/edge/SSR. Right: "Control Plane" (CMA) with arrows to CI/CD, admin scripts, backend services. with the deliveryClientand managementClientseparation. Highlight the different hosts ( cdn.contentstack.iovs api.contentstack.io) and different auth headers ( access_tokenvs authorization). |
| Regions (Outline items 4-5) |
Contentstack dashboard: navigate to Settings > Stack to show the region indicator. vs .com TLD difference for AWS NA. diagnostic -- hit cdn.contentstack.ioand eu-cdn.contentstack.com with the same credentials, show one returns 200 and the other returns 401. and the @timbenniks/contentstack-endpointshelper. |
| REST vs GraphQL (Outline items 6-7) |
Postman or terminal: execute the REST query for blog posts with include[]=author. Show the full response payload with all fields. , url, and author title+ bio. Show the trimmed response. pattern for references ( authorConnection { edges { node { ... on Author { title } } } }). |
| Authentication (Outline items 8-9) |
Contentstack dashboard: Settings > Tokens. Create a delivery token -- show the environment scope. helper that returns different headers for "published"vs "preview"modes, plus the managementHeaders constant. Highlight the comment: "managementHeaders never leaves trusted server code." |
| Rate Limits and Errors (Outline items 10-11) |
Code editor: show the resilientFetchfunction with error classification ( classifyError), exponential backoff calculation, and rate limit header logging. header counting down to zero, then the 429 response. |
Veda Scenario Thread
Veda is a fashion and lifestyle brand building a headless storefront on Contentstack. Use Veda throughout this video to ground every concept in a real project context.
- Two APIs, two jobs: Veda's Next.js storefront fetches product pages, collection listings, and editorial content through CDA. A separate backend service handles content migrations, automated tagging, and bulk publishing through CMA. Two codebases, two token types, two reliability contracts.
- Decision framework: walk through the five questions using Veda's "Related Products" strip. Intent: render published products for shoppers (CDA). Data state: published (CDA). Runtime: edge-rendered storefront (no management creds). Token: delivery token safe in browser. Blast radius of misuse: reads only, no data integrity risk.
- Regions: Veda's primary market is Europe. Their stack is on AWS EU. Every base URL uses the eu- prefix. When an American contractor onboarded and copied cdn.contentstack.io from a tutorial, requests returned empty results with no error message -- a classic region mismatch.
- REST vs GraphQL: Veda uses REST via the SDK for standard product detail pages (simple, cacheable, SDK handles includes). For the homepage -- which pulls hero content, featured collections, editorial picks, and navigation items from four content types -- they use a single GraphQL query to avoid four separate REST calls.
- Authentication: Veda's delivery token is scoped to the production environment and is safe in the Next.js client bundle. The management token lives only in a backend service that runs nightly content sync jobs. When the marketing team asked for a "quick admin panel" in the storefront, the engineering team said no -- management tokens do not belong in client-facing code.
- Rate limits: during Black Friday content preparation, Veda's ops team ran a migration script that bulk-published 2,000 product entries. At CMA's 10 req/s limit, the script started hitting 429s after the first batch. They added exponential backoff with jitter, read X-RateLimit-Remaining to throttle proactively, and completed the publish in 8 minutes instead of crashing in a retry storm.
- Error codes: a junior developer on Veda's team got a 404 when querying a product entry that definitely existed. The UID was correct, the token was correct -- but the SDK was configured for Contentstack.Region.US instead of Contentstack.Region.EU. The entry did not exist in the NA region. Region mismatch masquerading as a missing resource.
Transitions
Item 1 to 2: "Now that you see these are two separate planes, the question becomes: how do you decide which one to use for any given integration?"
Item 2 to 3: "The decision framework handles most cases cleanly, but there is one nuance worth calling out -- what about content that is not yet published?"
Item 3 to 4: "Once you know which API plane you need, the next thing to get right is the base URL -- and that depends entirely on your stack's region."
Item 4 to 5: "Knowing the regions exist is one thing -- let me show you exactly where to find yours and how to configure it."
Item 5 to 6: "With the right endpoint locked in, you have one more architectural choice: do you query with REST or GraphQL?"
Item 6 to 7: "Theory is useful, but seeing both side-by-side makes the tradeoff concrete."
Item 7 to 8: "You have picked your API plane, your region, and your query surface -- now you need the credentials to actually make the call."
Item 8 to 9: "Understanding token types is half the job. The other half is making sure each token only exists where it belongs."
Item 9 to 10: "Your tokens are in place and your queries are running -- but what happens when you send too many too fast?"
Item 10 to 11: "Rate limits are one kind of error. Let me walk you through every error code you are likely to see and exactly what each one means for your code."
Closing to Video 6: "You now have the full picture of Contentstack's API surface: which plane to use, which region to target, which query format to choose, how to authenticate, and how to handle errors. In Video 6, we will put this into practice with the SDK, CLI tooling, and developer workflow patterns."
Common Mistakes to Call Out
- Using CMA GET endpoints for frontend delivery. It works locally. It returns data. But you are shipping a management token to the browser, getting no CDN caching, and mixing your reliability planes. Classify endpoints by intent, not by HTTP verb.
- Hardcoding base URLs instead of using SDK region constants. Copy-pasting cdn.contentstack.io from a tutorial when your stack is on EU or Azure. The SDK has Contentstack.Region.EU for a reason -- use it.
- Confusing .io and .com TLDs. AWS NA uses contentstack.io. Every other region uses contentstack.com. Changing the prefix but keeping the wrong TLD produces silent failures.
- Choosing GraphQL to avoid learning REST query syntax. GraphQL is not "better REST." If your queries are simple and the SDK handles them well, GraphQL adds complexity without benefit.
- Assuming GraphQL supports mutations. GraphQL CDA is read-only. All writes, workflow changes, and admin actions require the REST-based CMA. Teams that architect write operations against GraphQL hit a wall.
- Shipping management tokens in client-side code. This is not a documentation issue -- it is an architecture issue. Management credentials belong only in trusted backends. If a token ends up in the browser, the blast radius is your entire stack.
- Sharing one management token across many services. If revoking that token breaks five unrelated systems, your security boundary is too broad. One credential per service responsibility.
- Retrying all errors uniformly. Wrapping every API call in a generic retry loop that treats 422 and 429 identically. Invalid payloads (422) will never succeed on retry -- you are just burning rate limit quota.
- No jitter in retry backoff. Fixed-delay retries across concurrent clients create a thundering herd. Every retry implementation must include randomness.
- Ignoring X-RateLimit-Remaining until you get a 429. Read the header on every response. Throttle proactively before hitting the ceiling, not reactively after crashing through it.
- Assuming a 404 means the resource does not exist. It might mean you are querying the wrong region. The API does not tell you "this resource exists in a different region" -- it just says "not found."
Notes
Use this space for recording notes, script drafts, or post-production feedback.