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

200OKRequest succeeded.
201CreatedResource created.
204No ContentSucceeded with no body (e.g. delete).
401UnauthorizedMissing / invalid / expired token.
403ForbiddenAuthenticated but lacking the required ability.
404Not FoundResource does not exist or is out of workspace scope.
422UnprocessableValidation failed — see the errors object.
429Too Many RequestsRate limit exceeded (60 req/min default).
500Server ErrorUnexpected 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.

422 Unprocessable Content
{
  "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.

422 Unprocessable Content
{
  "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.

401 Unauthorized
{
  "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=.

GET/api/contacts?page=2&per_page=25
Paginated collection
{
  "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.