Reference
Errors, auth, and limits
Status codes, auth edge cases, rate-limit behavior, and practical troubleshooting for both public and internal routes.
Parchment uses standard HTTP status codes and structured JSON error bodies, but route families have different auth expectations. The public catalog behaves differently from workspace, billing, and inventory routes.
The most common issues are invalid query parameters (400), missing or bad auth (401), insufficient permissions (403), and rate-limit exhaustion (429).
Status codes
| Status | Where you see it | Meaning |
|---|---|---|
| 200 | Most successful GETs and writes | Request succeeded. |
| 201 | Workspace create, workspace message save | Resource created. |
| 307 | /docs section redirects and legacy docs handoff | Temporary redirect to the canonical docs path. |
| 400 | Missing query params, bad form payloads, unsupported import files, and invalid catalog dates or numeric values | The caller provided an invalid request. |
| 401 | Missing or invalid session or API key | Authentication required. |
| 403 | Member role checks, admin checks, ownership failures | Authenticated but not allowed to perform the action. |
| 404 | Missing workspace, shared bean, or owned resource | The resource is absent or not visible to the caller. |
| 409 | Billing plan conflicts and bundled membership management limits | The request is valid but conflicts with current subscription state. |
| 429 | Public catalog API-key requests or AI provider backpressure | Quota or provider rate limit reached. |
| 499 | Cancelled chat requests | The caller aborted the request before completion. |
| 500 | Unhandled internal failures | Unexpected server-side error. |
| 502 | Workspace summarize provider failures | Upstream model or service dependency failed. |
Representative error bodies
400 Invalid query parameter
{
"error": "Invalid query parameter",
"message": "Query parameter \"stocked_date\" must use YYYY-MM-DD format",
"details": {
"parameter": "stocked_date",
"value": "30",
"expected": "YYYY-MM-DD"
}
}401 Authentication required
{
"error": "Authentication required"
}403 Member role required
{
"error": "Member role required"
}409 Subscription conflict
{
"error": "You already have an active API subscription. Use subscription management to change intervals."
}429 Public catalog quota exceeded
{
"error": "Rate limit exceeded",
"message": "API rate limit exceeded for your subscription plan",
"limit": 200,
"remaining": 0,
"resetTime": "2026-05-01T00:00:00.000Z"
}Edge cases worth knowing
- For external catalog access, prefer /v1/catalog. Use an API key for machine-to-machine access or authenticate the CLI with purvey auth login.
- Anonymous /v1/catalog calls use the same public query surface as other public callers. If page is supplied without limit, the route falls back to 15 rows; if both page and limit are omitted, the canonical listing response defaults to 100 rows.
- GET /api/beans with no session and no valid share token returns an empty data array, not a 401. Do not mistake that behavior for public inventory access.
- Catalog rate-limit headers only exist on API-key requests. Anonymous and session requests to /v1/catalog do not emit X-RateLimit-* headers.
- An invalid Authorization header on the public catalog can turn what looks like an anonymous request into a 401 because the route detects an auth attempt that failed.
- /api-dashboard/keys/generate returns the plaintext apiKey only at creation time. Plan Console UX and support docs around that one-time reveal.
- Cookies only matter when they resolve to a valid first-party session. A stray Cookie header is not part of the public API contract.
- /api/catalog-api is a deprecated API-key-only alias. It should not be treated as an anonymous or session-friendly discovery route.
- Workspace and chat routes mostly use member-role enforcement, so 403 is often the expected failure for logged-in non-members.
- AI-backed helpers can return upstream rate-limit or provider errors that are operational rather than domain-model failures.
Troubleshooting path
- External integration failing? Confirm it is calling /v1/catalog, not an internal /api/* route.
- Getting a 400 on catalog? Double-check date inputs like stocked_date=YYYY-MM-DD and any other validated query params.
- Unexpected 403 on product routes? Check role and ownership assumptions before debugging auth cookies.
- Hit a 429 on catalog? Inspect X-RateLimit-* and Retry-After or upgrade the plan in the Parchment Console.
- Need to validate workflows outside the browser? The CLI is usually the cleanest supported interface.