Versions and errors
Use expected versions for safe writes and handle machine-readable errors deliberately.
Version-bound writes
PATCH /api/v1/posts/{postId}, restore, and publish operations use the current tip version to prevent lost updates. Scheduling instead pins an existing versionNumber and a future publishAt UTC epoch second; it can publish that version after newer edits. Site, theme, and signup form changes use expectedUpdatedAt.
{
"expectedVersionNumber": 3,
"title": "Revised title"
}
When another write has created version 4, a request expecting version 3 returns HTTP 409 with CONFLICT.
Error model
REST errors are machine-readable and use the HTTP status that matches the failure:
| Status | Typical code |
|---|---|
400 |
VALIDATION_ERROR |
401 |
UNAUTHORIZED |
403 |
FORBIDDEN |
404 |
NOT_FOUND |
409 |
CONFLICT |
402 |
BILLING_REQUIRED |
429 |
RATE_LIMIT |
REST errors have an error object with code, message, optional details, and optional retryAfterSeconds. Plan blockers, including BILLING_REQUIRED, draft caps, media quotas, and hosted request quotas, include a dashboard billing link in details.upgradeUrl and in the message: “Upgrade to vibecms Cloud: <url>”. The URL uses the installation’s APP_URL and /dashboard/settings?tab=billing.
For MCP tools/call, the error tool result has isError: true; the same code, message, and details appear in both JSON text content and structuredContent. Give the owner the returned upgrade link rather than constructing a URL or attempting billing changes. Leave saved drafts intact.
Do not retry validation, authorization, or conflict failures unchanged. Network failures and rate limits may be retried only while the original user request remains active.