Authentication
All API requests require a Bearer token in the Authorization header. Postlark supports two authentication methods.
API Key (recommended for MCP, CLI, automation)
Section titled “API Key (recommended for MCP, CLI, automation)”Authorization: Bearer pk_live_xxxxxxxxxxxxGenerate keys in Dashboard → Settings → API Keys. Each key is bound to a specific blog.
JWT Session (Dashboard only)
Section titled “JWT Session (Dashboard only)”The Dashboard uses Supabase JWT tokens for session-based authentication:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...When using JWT auth, Postlark auto-selects your first blog. To target a specific blog, include the X-Blog-Id header:
X-Blog-Id: blog-uuid-hereScopes
Section titled “Scopes”API keys support scoped permissions. Each scope controls access to a specific set of operations.
| Scope | Description |
|---|---|
* | Full access (all scopes) |
posts:read | Read posts (list, get) |
posts:write | Create, update, delete, publish, schedule posts |
blogs:read | Read blog settings |
blogs:write | Update blog settings, manage domains |
analytics:read | Read analytics data |
keys:manage | Create and revoke API keys |
When you create a new API key, the default scope is ["*"] (full access). You can restrict scopes when generating a key in the Dashboard or via the API.
Token Expiration
Section titled “Token Expiration”API keys do not expire by default. You can revoke a key at any time from Dashboard > Settings > API Keys or via DELETE /blogs/:id/api-keys/:keyId.
JWT session tokens expire according to Supabase Auth settings (default: 1 hour). The Dashboard handles token refresh automatically.
If a revoked or expired token is used, the API returns 401 Unauthorized.
Rate Limits
Section titled “Rate Limits”| Plan | Requests/hour |
|---|---|
| Free | 60 |
| Starter | 300 |
| Creator | 1,000 |
| Scale | 10,000 |
| Enterprise | 10,000+ |
Every response includes rate limit headers:
X-RateLimit-Limit: 300X-RateLimit-Remaining: 299X-RateLimit-Reset: 1711324800When exceeded, you’ll receive a 429 response with retry_after seconds.
See the full Rate Limits reference for Post Packs and plan details.
Error Format
Section titled “Error Format”All errors follow a consistent JSON format:
{ "error": "not_found", "message": "Post not found"}| Status | Description | Example |
|---|---|---|
| 400 | Invalid input | "title is required" |
| 401 | Missing or invalid token | "Invalid API key" |
| 403 | Plan upgrade required | "Post limit exceeded. Free plan allows 10 total posts." |
| 404 | Resource not found | "Post not found" |
| 409 | Duplicate resource | "slug \"my-post\" is already taken" |
| 429 | Rate limit exceeded | "Rate limit exceeded. Limit: 60 requests/hour." |
| 500 | Server error | "Internal server error" |
Base URL
Section titled “Base URL”https://api.postlark.ai/v1Try the interactive API explorer: api.postlark.ai/docs