POST /groups, PUT /groups/{id}, PUT /groups/{id}/members — all with a single 422 validation errors). No endpoint formally documents 401, 403, 404, or 500.
This gap doesn’t mean those errors don’t occur — they do. It means partner integrations must build defensive error handling without spec guidance about exact response shapes or status codes. This page covers what to expect from the live API, the classification framework that handles each case appropriately, and the patterns that produce reliable production code.
⚠️ Spec gap: The Volunteer OpenAPI spec documents error responses on only three endpoints (all 422 validation errors). The rest of the spec is silent on error responses entirely. The patterns on this page reflect what the live API likely returns based on common REST conventions; confirm against actual responses for production-critical workflows.
What the spec confirms
The three endpoints that do document error responses:
Everything else is undocumented. No endpoint exposes the shape of an error response, the fields available on a problem object, or the headers returned with error responses.
What the live API likely returns
Based on common conventions for Laravel-style APIs (which Volunteer appears to be):
These shapes are common in Laravel-based APIs but aren’t formally documented for Volunteer. Don’t switch business logic on specific error message strings — they’re not a contract.
The defensive classification framework
The classifier turns any error response into a category that determines how to handle it:Per-status handling in depth
401 Unauthorized: don’t retry
A 401 means the token isn’t being accepted. Common causes:
The response:
401s and noise. Pause the customer’s work; alert ops. See Authentication: Handling auth failures.
403 Forbidden: also don’t retry
A 403 means the token is valid but doesn’t have permission for the specific endpoint. Causes:
401, don’t retry — the permission isn’t going to change in seconds.
404 Not Found: handle gracefully
A 404 from a single-resource endpoint (e.g., GET /users/12345) means the user with that ID doesn’t exist in the customer’s organization. Causes:
404 — a non-existent resource will continue to not exist on retry. Return null and let the caller handle the absence.
422 Validation Error: the documented case
The three endpoints that document 422 (POST /groups, PUT /groups/{id}, PUT /groups/{id}/members) return validation errors when the request body doesn’t pass validation. Other endpoints that accept request bodies (POST /projects, POST /users, PUT /projects/{id}) almost certainly return 422 similarly even though it’s undocumented.
The body shape (assuming Laravel conventions):
422 — the same payload will fail validation again. Surface the field-level errors to the user (or your integration’s logs) so the bad data can be corrected.
429 Too Many Requests: rate limited
429 isn’t documented in the spec but rate limits likely exist at the platform level. When it happens:
5xx Server errors: retry with backoff
Server errors (500, 502, 503, 504) are typically transient. Retry with exponential backoff:
A complete error-handling pattern
Putting it together as a reusable client:not_found, validation_failed, etc.).
Surfacing errors meaningfully
The error pattern produces good developer experience when integrated properly:Don’t swallow errors silently
Surface field-level validation errors
Distinguish user-facing from internal errors
Monitoring error rates
Track these metrics for any production Volunteer integration:
Per-customer breakdowns matter. A customer-specific spike in
401s indicates that customer’s token is bad; a platform-wide spike in 503s indicates a VOMO issue not specific to any one customer.
A common-error-cases checklist
For a new Volunteer integration, walk through these cases explicitly:- Token is invalid (
401) → pause customer; alert - Token lacks permission (
403) → alert; don’t retry - Resource doesn’t exist (
404) → return null; caller decides - Request body invalid (
422) → surface field-level errors - Rate limited (
429) → honorRetry-After; back off - Server error (
5xx) → retry with exponential backoff - Network error → retry as transient
- Unexpected
4xx→ log and surface; don’t retry - All errors logged with sufficient context (customer ID, endpoint, status, body)
- Metrics emitted for each error class
- Field-level validation errors surfaced to UI / caller
- User-facing messages distinct from internal logs
Where to go next
The retry pattern for429 responses in detail.The broader recovery patterns — circuit breakers, dead-letter queues, classification.The auth-failure handling section in depth.Error patterns specific to multi-page reads.