This package is in pre-release. The API may change before v1.0.

Introduction

API Toolkit is a Laravel package that gives you everything you need to build JSON:API compliant REST APIs. It handles resource serialization, query parameters, pagination, filtering, sorting, error responses, and even generates your OpenAPI documentation automatically.

Features

  • JSON:API Resources - Serialize Eloquent models into spec-compliant responses with relationships, links, and metadata
  • Query Builder - Fluent API for filtering, sorting, including relationships, and paginating
  • Built-in Filters - Exact, partial, date, scope, and search filters out of the box, with support for custom filters
  • Scout Integration - Full-text search via Laravel Scout (Typesense, Meilisearch, Algolia)
  • Sparse Fieldsets - Let clients request only the attributes they need
  • Pagination - Offset and cursor-based pagination with configurable page sizes
  • Error Handling - Automatic exception rendering in JSON:API format, including validation errors with field pointers
  • OpenAPI Generation - Auto-generate OpenAPI 3.1 specs from your routes and resources
  • Testing Utilities - Chainable assertions purpose-built for JSON:API responses
  • Middleware - Force JSON:API content type on all responses

Why API Toolkit?

Laravel 12.45 introduced JsonApiResource for basic JSON:API serialization, covering type/id/attributes structure, relationships, included resources, and sparse fieldsets.

API Toolkit builds on top of that with:

  • Type-safe resources - Typed model parameters instead of magic $this->name via __get
  • Non-Eloquent support - Works with any object: DTOs, Carbon, stdClass, and more
  • Filtering - Exact, partial, date, and scope-based filters via ?filter[status]=active
  • Sorting - ?sort=-created_at parsed and applied automatically
  • Pagination - Offset and cursor-based with meta and links
  • Query validation - Strict rejection of unknown parameters
  • Error responses - JSON:API errors with source pointers for validation failures
  • OpenAPI 3.1 - Auto-generated from your routes and resources
  • Testing - Chainable assertions for Pest and PHPUnit

Requirements

  • PHP 8.4+
  • Laravel 13.0+

Quick Example

Define a resource:

use BlueBeetle\ApiToolkit\Resources\Resource;

class ProductResource extends Resource
{
    public function attributes($model): array
    {
        return [
            'name'  => $model->name,
            'price' => $model->price,
            'sku'   => $model->sku,
        ];
    }

    public function relationships(): array
    {
        return [
            'category' => CategoryResource::class,
        ];
    }
}

Use it in a controller:

use App\Http\Resources\ProductResource;
use App\Models\Product;
use BlueBeetle\ApiToolkit\Http\Response;
use BlueBeetle\ApiToolkit\QueryBuilder;
use Illuminate\Http\Request;

class ProductController
{
    public function index(Request $request)
    {
        return QueryBuilder::for(Product::class, $request)
            ->fromResource(ProductResource::class)
            ->paginate();
    }

    public function show(Product $product, Response $response)
    {
        return $response->success($product, ProductResource::class);
    }
}

Response:

{
  "data": {
    "type": "products",
    "id": "prod_abc123",
    "attributes": {
      "name": "Widget Pro",
      "price": 29.99,
      "sku": "WGT-001"
    },
    "relationships": {
      "category": {
        "data": { "type": "categories", "id": "1" }
      }
    }
  }
}