Panahashi uses a consistent error response format across all endpoints. When a request fails, the API returns a JSON object with a machine-readableDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/AndrewwCO/Panahashi-Backend/llms.txt
Use this file to discover all available pages before exploring further.
code and a human-readable message. Successful responses are always wrapped in an ApiResponse<T> envelope. Understanding the error shape and the status codes the API uses makes it straightforward to write reliable client-side error handling.
ApiError response shape
Every error response — regardless of cause — uses the sameApiError structure.
A machine-readable error identifier. Use this in your client code to branch on specific error types.
A human-readable description of what went wrong. May be in Spanish for auth errors.
Example error response
Error responses are not wrapped in
ApiResponse. They are returned as a plain ApiError object directly at the top level.HTTP status codes
200 OK / 201 Created — Success
200 OK / 201 Created — Success
The request succeeded. The response body is an
ApiResponse<T> with success: true and the result in data. 201 Created is used for resource creation endpoints (e.g. POST /api/v1/orders).400 Bad Request — Validation or malformed input
400 Bad Request — Validation or malformed input
The request body or query parameters are invalid. This can come from a failed input validation (
VALIDATION_ERROR) or a business rule rejection (BAD_REQUEST).401 Unauthorized — Invalid or missing token
401 Unauthorized — Invalid or missing token
403 Forbidden — Insufficient role
403 Forbidden — Insufficient role
The token is valid but the caller’s role does not permit the action. For example, a
CUSTOMER trying to update an order status gets a 403.404 Not Found — Resource does not exist
404 Not Found — Resource does not exist
The requested resource could not be found in Firestore. Thrown when a route handler calls
noSuchElementException (or equivalent).500 Internal Server Error — Unexpected failure
500 Internal Server Error — Unexpected failure
An unhandled exception occurred on the server. The response body always contains a generic message to avoid leaking internals.
Error codes reference
| Code | HTTP status | Cause |
|---|---|---|
UNAUTHORIZED | 401 or 403 | Missing/invalid Firebase token, or caller’s role is insufficient |
BAD_REQUEST | 400 | Malformed request body or business rule violation (IllegalArgumentException) |
VALIDATION_ERROR | 400 | Request failed Ktor’s RequestValidationException checks |
NOT_FOUND | 404 | Resource not found in Firestore (NoSuchElementException) |
INTERNAL_ERROR | 500 | Unhandled server exception |
Common errors and how to resolve them
| Scenario | Code | HTTP | Resolution |
|---|---|---|---|
| Firebase token expired | UNAUTHORIZED | 401 | Call FirebaseAuth.currentUser.getIdToken(true) to force-refresh the token and retry. |
No Authorization header sent | UNAUTHORIZED | 401 | Ensure every protected request includes Authorization: Bearer <id_token>. |
CUSTOMER calls a BAKER-only route | UNAUTHORIZED | 403 | Check the endpoint’s required role in the roles reference before calling. |
bakeryId query param missing on product list | BAD_REQUEST | 400 | Include ?bakeryId=<id> in the request URL. |
| Submitting a review for a non-existent order | NOT_FOUND | 404 | Verify the orderId exists and belongs to the authenticated user. |
| Negative or zero price on product creation | VALIDATION_ERROR | 400 | Check validation error message for the specific field(s) that failed. |
| Firestore service temporarily unavailable | INTERNAL_ERROR | 500 | Retry with exponential backoff. If the issue persists, contact support. |
ApiResponse wrapper
Successful responses are always wrapped inApiResponse<T>:
Always
true for successful responses.The response payload. The type varies by endpoint — see each endpoint’s reference for the concrete type returned.
Optional human-readable message. Often
null on success, populated on some create/action endpoints.Successful single-object response
Pagination with PagedResponse
List endpoints that return many results usePagedResponse<T> instead of a plain array. Pass page and pageSize as query parameters to control which slice you receive.
Items on the current page.
Current page number (1-based).
Maximum items per page as requested.
Total item count across all pages.
true when additional pages exist beyond the current one.Fetching the second page of products
PagedResponse example
When
hasMore is false, you have received the final page. Requesting a page number beyond total / pageSize returns an empty data array.