EmDash ships with a granular API token system that mirrors its plugin sandbox philosophy. Each token declares exactly which capabilities it carries—content read, content write, media access, user management—and can be set to expire after a defined period. That much is visible in the admin panel. What the documentation won’t tell you is how to design a token strategy that survives production loads, third-party integrations, and the occasional audit.
This guide assumes you’ve already generated a token and connected a service to the EmDash API. We’re skipping the “how to click the button” part. Instead, we’ll cover the decisions that separate a secure integration from one that leaks data or breaks under scale.
Treat each token as a potential attack surface, rotate aggressively, and never assume a token with content:read is safe to expose.
The Capability Manifest Model
Every EmDash API token is bound to a capability manifest—a JSON-like declaration of what the token can do. This isn’t a role-based system where “editor” grants a fixed set of permissions. You define the scope per token. For example:
“`json
{
“capabilities”: [“content:read”, “content:write”],
“collections”: [“posts”, “projects”],
“expires”: “2026-12-31T23:59:59Z”
}
“`
The non-obvious part: capabilities are not inherited from the user who creates the token. They are independently assigned. That means a token can have more permissions than its creator—or fewer. An author-level user can generate a token that writes to any content type, as long as the admin has enabled that capability in the token creation UI. This is by design: tokens are meant for machine-to-machine communication, not to mirror human roles.
Practical implication: Always audit token manifests against the principle of least privilege. A token that reads posts and sends email (a common plugin pattern) cannot accidentally read user profiles or modify the database. But if you grant media:writecodecode to a token used only for content imports, you’ve opened an unnecessary attack surface.
Integration Patterns That Actually Work
1. Static Publishing Workflows
The most common external integration is a static site generator (SSG) that pulls content from EmDash at build time. For this, create a token with content:readcodecode scoped to the specific collections you need. Do not use a token with content:writecodecode unless the build process also pushes data back (e.g., form submissions or comments).
The trick: EmDash’s API supports conditional requests via ETagcodecode headers. If your SSG sends the token with If-None-Matchcodecode, you can skip re-fetching unchanged content. This halves build time on large sites and reduces worker invocation costs.
2. Headless Frontend with Live Preview
For a JavaScript frontend (e.g., Next.js or Astro) that needs draft preview, you might be tempted to expose a token with content:readcodecode directly in the client. Don’t. Tokens are server-side secrets. Instead, proxy requests through your own API endpoint that checks authentication before forwarding the token.
EmDash’s MCP server can help here: it exposes a read-only interface for agents, but you can also use it as a backend-to-backend bridge. The MCP server authenticates via its own token (typically a site-level secret), which is separate from user tokens.
3. Automated Content Migrations
The WordPress import tool uses a temporary token generated during the migration flow. For custom migrations (e.g., from another CMS or a CSV pipeline), generate a dedicated token with content:writecodecode and media:writecodecode, but set a short expiration—24 hours at most. This limits blast radius if the token leaks during the batch upload.
Token Lifecycle Management
Rotation Strategy
EmDash tokens can expire, but there is no built-in auto-rotation. You must implement it yourself. The standard approach in production environments is to:
- Create two tokens per integration: an active token and a standby token.
- Rotate every 90 days—or sooner if the token scope changes.
- Use the EmDash API’s
POST /api/tokens/revokecodecode endpoint to invalidate the old token after the new one is confirmed working.
Based on reported incident response data, improperly scoped tokens account for roughly 40% of API-related data breaches in CMS integrations. A strict rotation schedule reduces the window of exposure to a maximum of 90 days per token.
Monitoring and Alerts
EmDash does not yet expose token usage logs in the admin dashboard. For production, you need to consume Cloudflare’s Workers logs or set up your own monitoring on the integration side. Track:
- 401 responses (invalid or expired token)
- 429 responses (rate limiting)
- Unusual geographic origins (indicates token theft)
If you see a spike in 401s from an unknown IP range, revoke the token immediately and rotate.
Non-Obvious Pitfalls
Token Proliferation
Every developer on your team creates their own token for local testing. Before long, you have dozens of tokens, half of them with content:writecodecode and no expiration. Set a policy: tokens for local development should have content:readcodecode only and expire in 7 days. Use the same token for all team members in a shared staging environment.
Rate Limits and Cost
Each API call consumes a Cloudflare Worker invocation. On the $5/month Workers Paid plan, you get 10 million requests. A misbehaving integration that polls every 5 seconds will burn through that allocation in under two weeks. Use conditional requests and cache aggressively. For polling integrations, set a minimum interval of 60 seconds—or better, use webhooks (once EmDash adds them).
Token Storage in Third-Party Services
When connecting EmDash to Zapier, Make, or a custom webhook receiver, the token is stored on their servers. If that service suffers a breach, your token is compromised. Mitigate by:
- Using read-only tokens for data export integrations.
- Setting expiration to the minimum viable duration (e.g., 30 days for a recurring sync).
- Revoking and replacing tokens on a regular schedule, even if the integration doesn’t require it.
The Edge Case: When Least Privilege Fails
Consider a token that needs to create posts and trigger an email notification. In EmDash, that requires two capabilities: content:writecodecode and email:sendcodecode. But what if the email service is down? The token still works for content creation, but the integration might fail silently.
The non-obvious solution: create two separate tokens—one for content operations, one for email—and let the integration handle the orchestration. This way, a failure in one capability doesn’t block the other. It also makes auditing easier: you can revoke the email token without affecting content publishing.
Summary of Recommendations
| Concern | Action |
|---|---|
| Token scope | Define per-token capability manifests; don’t reuse user roles |
| Rotation | Every 90 days with a standby token |
| Client-side exposure | Never; proxy through a backend endpoint |
| Expiration | Short-lived for batch jobs (24h), longer for persistent integrations (90d max) |
| Monitoring | Track 401s and 429s via Workers logs |
| Third-party storage | Use read-only tokens and short expirations |
EmDash’s API token system is more flexible than WordPress’s application passwords, but that flexibility demands discipline. Treat each token as a potential attack surface, rotate aggressively, and never assume a token with content:readcodecode is safe to expose. The architecture can handle it; the question is whether your integration process does.
- What is a capability manifest in EmDash API tokens?A capability manifest is a JSON-like declaration that defines exactly what a token can do, such as content:read or content:write, scoped to specific collections.
- How should you handle token exposure in headless frontends?Never expose tokens directly in client-side code. Instead, proxy requests through your own API endpoint that checks authentication before forwarding the token.
- What is the recommended token rotation schedule?Rotate tokens every 90 days with a standby token to ensure continuous operation and minimize security risks.