Errors
Errors are JSON with a machine-readable code:
{ "code": "not_found", "message": "Post not found." }
Validation failures return field-keyed errors from DRF ({"title": ["This field is required."]}).
Status codes
| Status | Shape | Meaning |
|---|---|---|
400 | {"code": "bad_request", "message": "..."} or field-keyed {"title": ["..."]} | Invalid input |
401 | {"message": "..."} | Missing/invalid/revoked/expired token |
403 | {"code": "forbidden", ...} (role denied) or {"message": "..."} (token scoped to another workspace) | Your role doesn't allow it, or the token is scoped to another workspace |
404 | {"code": "not_found", ...} | Wrong id or wrong workspace |
429 | {"code": "rate_limited", ...} | Slow down — see Rate limits |
The two 403s
Your token authenticated fine but isn't allowed to do that. Two distinct causes, told apart by the message:
- "This API token is restricted to another workspace." — the token was created scoped to one workspace. Use it only there, or create an all-workspaces token.
- "Access denied." — your own role in that workspace doesn't permit the action (e.g. members can edit their own posts but not others'; publishing needs admin/owner or being the creator). This matches exactly what you could do in the app.
For step-by-step diagnosis of 401/403/429, see Troubleshooting API errors.