PHPackages                             intermax/laravel-json-api - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. intermax/laravel-json-api

ActiveLibrary[API Development](/categories/api)

intermax/laravel-json-api
=========================

Reusable filters, resources and other API tools.

2.3.0(1y ago)27.2k[5 issues](https://github.com/Intermax-Cloudsourcing/laravel-json-api/issues)PHPPHP &gt;=8.2CI passing

Since Sep 9Pushed 1y ago3 watchersCompare

[ Source](https://github.com/Intermax-Cloudsourcing/laravel-json-api)[ Packagist](https://packagist.org/packages/intermax/laravel-json-api)[ RSS](/packages/intermax-laravel-json-api/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (7)Dependencies (9)Versions (30)Used By (0)

Laravel JSON:API
================

[](#laravel-jsonapi)

Laravel API is a package to quickly build an API according to the JSON:API specification. It also generates OpenAPI documentation on the fly based on your API endpoints.

- [Installation](#installation)
- [Configuration](#configuration)
- [Basic usage](#basic-usage)
- [Query Parameters](#query-parameters)
    - [CollectionRequest](#collectionrequest)
    - [Controller](#controller)
    - [Filter types](#filter-types)
- [MutationRequest](#mutation-requests)
- [OpenAPI generation](#openapi-generation)

Installation
------------

[](#installation)

```
composer require intermax/laravel-json-api
```

Configuration
-------------

[](#configuration)

To render exceptions in JSON:API format, you can add the middleware `Intermax\LaravelJsonApi\Middleware\RenderJsonApiExceptions` to applicable routes. A sensible example would be in the HTTP Kernel in the API middleware group:

```
// app/Http/Kernel.php

use Intermax\LaravelJsonApi\Middleware\RenderJsonApiExceptions;
...
    protected $middlewareGroups = [
        ...

        'api' => [
            ...
            RenderJsonApiExceptions::class,
        ],
    ];
```

Basic Usage
-----------

[](#basic-usage)

To create an endpoint you just create a Laravel route like you're used to doing. After that you need to create a resource. Let's assume we make an endpoint that returns a `UserResource`:

```
use Illuminate\Http\Request;
use Intermax\LaravelJsonApi\Resources\JsonApiResource;

class UserResource extends JsonApiResource
{
    public function getAttributes(Request $request): array
    {
        return [
            'email' => $this->resource->email,
            'name' => $this->resource->name,
        ];
    }

    public function getRelations(Request $request): ?array
    {
        return null;
    }

    public function getLinks(Request $request): ?array
    {
        return null;
    }
}
```

After that you should create your controller method. Generally you would want an API Resource Controller. If you return the resource you just made your first endpoint with the Laravel API package:

```
use Illuminate\Http\Request;
use App\Http\Resources\UserResource;

class UserController
{
    public function show(User $user): UserResource
    {
        return new UserResource($user);
    }
}
```

> ❗ **TIP**: Make sure to type hint your resource on the controller method so Open API docs can be generated correctly. Read more about this at [Open API generation](open-api-generation.md)

Query Parameters
----------------

[](#query-parameters)

You might want ways to apply filters, sorts and includes to your requests. With JSON:API this is done by applying a `filter`, `sort` and include variables to the query string:

```
/users?filter[isAdmin]=true&sort=name&include=team

```

### CollectionRequest

[](#collectionrequest)

With this package you can configure some predefined filters or add your own. You can also add includes and sorts. To do this you can add a `CollectionRequest` to your controller method. Essentially this is an extended [FormRequest](https://laravel.com/docs/8.x/validation#form-request-validation). Your custom `CollectionRequest` needs to extend the `Intermax\LaravelJsonApi\Requests\CollectionRequest`. It might look like this:

```
namespace App\Http\Requests;

use Intermax\LaravelJsonApi\Filters\ScopeFilter;
use Intermax\LaravelJsonApi\Filters\OperatorFilter;
use Intermax\LaravelJsonApi\Requests\CollectionRequest;
use Intermax\LaravelJsonApi\Sorts\Sort;
use Intermax\LaravelJsonApi\Includes\Relation;

class UserCollectionRequest extends CollectionRequest
{
    public function filters(): array
    {
        return [
            new OperatorFilter('createdAt'),
            new ScopeFilter('isAdmin'),
        ];
    }

    public function sorts(): array
    {
        return [
            new Sort('name'),
        ];
    }

    public function includes(): array
    {
        return [
            new Relation('team'), // Eloquent relation name
        ];
    }
}
```

This specific `CollectionRequest` adds two filters, `filter[createdAt]` and `filter[isAdmin]`. To see how these specific filters work, see [filter types](#filter-types).

### Controller

[](#controller)

To make the filters, includes and sorts actually do their magic, we need a little more. In the controller the `QueryResolver` needs to be used to apply the filters to the Eloquent query. Under the hood this uses the [laravel-query-builder](https://github.com/spatie/laravel-query-builder) package from spatie.

```
use Intermax\LaravelJsonApi\Requests\QueryResolver;

class UserController
{
    public function index(UserCollectionRequest $request, QueryResolver $queryResolver): UserResourceCollection
    {
        $query = User::query();

        $queryResolver->resolve($request, $query);

        $query->where(...) // You can alter the query further if needed

        return new UserResourceCollection($query->jsonPaginate());
    }
}
```

### Filter Types

[](#filter-types)

This package provides two types of filters out of the box. One is the `ScopeFilter`. Like its name implies this will call the scope with the value that's being sent.

The second one is called the `OperatorFilter`. It allows you to query with a set of operators:

- Equals: `filter[column]=value` or `filter[column][eq]=value`
- Not equals: `filter[column][nq]=value`
- Greater than: `filter[column][gt]=value`
- Less than: `filter[column][lt]=value`
- Greater than or equals: `filter[column][gte]=value`
- Less than or equals: `filter[column][lte]=value`
- Contains: `filter[column][contains]=value`

Allowed operators can be specified (default all are allowed):

```
use Intermax\LaravelJsonApi\Filters\OperatorFilter

new OperatorFilter(
    fieldName: 'name',
    allowedOperators: [
        'eq',
        'nq',
        'contains',
    ],
);
```

Mutation Requests
-----------------

[](#mutation-requests)

For POST, PUT or PATCH requests this package provides an extendable base request for convenience. Instead of a regular `FormRequest` you know from Laravel it should extend the `MutationRequest`. This class helps you to adhere to the JSON:API specification for your requests:

- It rejects requests without the correct content type (`application/vnd.api+json`)
- The implementing class can provide rules for the `attributes` and `relationships` fields
- It has methods to retrieve `validatedAttributes` and `validatedRelationships`

> ⚠️ **WARNING**: Be aware that if you were previously not checking for the content type you could easily create a breaking change in your application.

### Usage

[](#usage)

An example implementation may look like this:

```
use Intermax\LaravelJsonApi\Requests\MutationRequest;

class UserUpdateRequest extends MutationRequest
{
    protected function type(): string
    {
        return 'users';
    }

    protected function attributeRules(): array
    {
        return [
            'email' => ['email'],
            'name' => ['string'],
        ]
    }
}
```

And in the controller you can use the methods to retrieve validated fields:

```
public function update(UserUpdateRequest $request, User $user): UserResource
{
    $user->update($request->validatedAttributes());

    return new UserResource($user);
}
```

OpenAPI Generation
------------------

[](#openapi-generation)

This package leverages the [Laravel Open API package](https://github.com/Intermax-Cloudsourcing/laravel-open-api) to provide a `/docs` endpoint (and `/docs/json` and `/docs/yaml` endpoints).

The open API package will scan for api routes, read FormRequests, determine ApiResources and try to guess the output of the resource. We aim to generate as much documentation as possible with a minimal amount of configuration.

There are a couple of things that need to be in place for this to work best:

- Use the CollectionRequest for 'collection-type' endpoints, even if you don't use Eloquent it will still be able to infer the query parameters. You can even validate query parameters with rules.
- Typehint the resource you want to return in your controller method.
- Use FormRequest validation for your POST/PUT/PATCH endpoints and include all fields in it (even if they have no validation). The package uses this to determine the request body.
- The package will get all your fields/attributes from the resource array.

### Improving resource attribute data types

[](#improving-resource-attribute-data-types)

If you look at the docs and see all your resource attributes are listed as string in the array, there is one more thing you can do to improve it. Wrap every field in a `Intermax\LaravelOpenApi\Generator\Values\Value` type object:

```
use Intermax\LaravelOpenApi\Generator\Values\StringValue;
use Intermax\LaravelOpenApi\Generator\Values\IntegerValue;
use Intermax\LaravelOpenApi\Generator\Values\NumberValue;
use Intermax\LaravelOpenApi\Generator\Values\DateTimeValue;
use Intermax\LaravelOpenApi\Generator\Values\BooleanValue;
use Carbon\Carbon;
use Intermax\LaravelJsonApi\Resources\JsonApiResource;

class UserResource extends JsonApiResource
{
    public function getAttributes(Request $request): array
    {
        return [
            'age' => new IntegerValue(fn () => Carbon::now()->diffInYears($this->resource->birthDate)),
            'email' => new StringValue(fn () => $this->resource->email),
            'name' => new StringValue(fn () => $this->resource->name),
            'createdAt' => new DateTimeValue(fn () => $this->resource->created_at),
            'isAdmin' => new BooleanValue(fn () => $this->resource->is_admin),
        ];
    }
}
```

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance29

Infrequent updates — may be unmaintained

Popularity25

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity78

Established project with proven stability

 Bus Factor1

Top contributor holds 57.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~63 days

Recently: every ~137 days

Total

28

Last Release

374d ago

Major Versions

0.13.0 → 1.0.02022-09-12

1.2.0 → 2.0.02024-05-07

PHP version history (5 changes)0.1.0PHP ^7.4.0

0.2.6PHP &gt;=7.4

0.7.0PHP &gt;=8.0

0.9.0PHP &gt;=8.1

2.0.0PHP &gt;=8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/66799a80d7f6bf4e0d024c1e06e66a3ec14495e2892c0861be3d060a0a0ec9e6?d=identicon)[phoogkamer](/maintainers/phoogkamer)

![](https://www.gravatar.com/avatar/22033bf3bc370af7632beaa0c40b05a672d56b835444d71c304d67c73634ed6b?d=identicon)[tomasvanrijsse](/maintainers/tomasvanrijsse)

![](https://www.gravatar.com/avatar/1d29f1e3a98167416d3c875395c17a008e312b5988a183c0a93998723be4d27c?d=identicon)[Intermax](/maintainers/Intermax)

---

Top Contributors

[![tomasvanrijsse](https://avatars.githubusercontent.com/u/1403466?v=4)](https://github.com/tomasvanrijsse "tomasvanrijsse (20 commits)")[![patrickhoogkamer](https://avatars.githubusercontent.com/u/1894838?v=4)](https://github.com/patrickhoogkamer "patrickhoogkamer (15 commits)")

---

Tags

apilaravelJSON-API

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/intermax-laravel-json-api/health.svg)

```
[![Health](https://phpackages.com/badges/intermax-laravel-json-api/health.svg)](https://phpackages.com/packages/intermax-laravel-json-api)
```

###  Alternatives

[darkaonline/l5-swagger

OpenApi or Swagger integration to Laravel

2.9k34.0M112](/packages/darkaonline-l5-swagger)[knuckleswtf/scribe

Generate API documentation for humans from your Laravel codebase.✍

2.3k12.2M45](/packages/knuckleswtf-scribe)[cloudcreativity/laravel-json-api

JSON API (jsonapi.org) support for Laravel applications.

7881.1M5](/packages/cloudcreativity-laravel-json-api)[nickurt/laravel-postcodeapi

Universal PostcodeApi for Laravel 11.x/12.x/13.x

97221.2k](/packages/nickurt-laravel-postcodeapi)[dystcz/lunar-api

Dystore API layer for Lunar e-commerce package

411.1k3](/packages/dystcz-lunar-api)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
