Errors & Conventions
Shared conventions for content types, validation errors, pagination and rate limiting across every endpoint.
Content type
Send Accept: application/json on every request. Without it, Laravel may redirect on validation errors instead of returning JSON. Bodies are JSON except for uploads, which use multipart/form-data.
Status codes
| 200 | OK | Request succeeded. |
| 201 | Created | Resource created. |
| 204 | No Content | Succeeded with no body (e.g. delete). |
| 401 | Unauthorized | Missing / invalid / expired token. |
| 403 | Forbidden | Authenticated but lacking the required ability. |
| 404 | Not Found | Resource does not exist or is out of workspace scope. |
| 422 | Unprocessable | Validation failed — see the errors object. |
| 429 | Too Many Requests | Rate limit exceeded (60 req/min default). |
| 500 | Server Error | Unexpected error. |
Error shapes
The API returns three distinct error envelopes depending on where the failure occurs. All three carry a field-keyed errors object or a message, so clients should handle each.
1 · Field validation (FormRequest)
Raised before the controller runs. Wrapped with success and status, with one array of messages per invalid field.
{
"success": false,
"status": 422,
"message": "The email field is required.",
"errors": {
"email": ["The email field is required."],
"password": ["The password field is required."]
}
}2 · Business-rule failure
Raised inside the controller (e.g. bad credentials on login). Note the message lives under errors.message as an array — there is no top-level message key.
{
"errors": {
"message": ["Invalid email or password"]
}
}3 · Auth / authorization failure
A missing or expired token returns 401; a valid token lacking the required ability returns 403. Both use a bare message.
{
"message": "Unauthenticated."
}Pagination
List endpoints backed by API Resource collections return Laravel's paginator envelope: a data array with links and meta. Use ?page= and, where supported, ?per_page=.
/api/contacts?page=2&per_page=25{
"data": [ { "id": 1, "first_name": "Jane" } ],
"links": {
"first": "https://api.axis.im/api/contacts?page=1",
"last": "https://api.axis.im/api/contacts?page=9",
"prev": null,
"next": "https://api.axis.im/api/contacts?page=2"
},
"meta": { "current_page": 1, "per_page": 25, "total": 214, "last_page": 9 }
}Rate limiting
The API middleware group applies throttle:60,1 (60 requests per minute) by default. Responses carry X-RateLimit-Limit and X-RateLimit-Remaining; exceeding the limit returns 429 with a Retry-After header.
Workspace scoping
The API is multi-tenant. The authenticated user's workspaces_id scopes every query, so a resource from another workspace surfaces as 404 rather than 403. IDs are only unique within a workspace context.