PHPackages                             lucite/apispec - 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. lucite/apispec

ActiveLibrary[API Development](/categories/api)

lucite/apispec
==============

v0.0.3(1y ago)06MITPHPPHP ^8

Since Sep 26Pushed 1y ago1 watchersCompare

[ Source](https://github.com/octoth0rpe/LuciteApiSpec)[ Packagist](https://packagist.org/packages/lucite/apispec)[ RSS](/packages/lucite-apispec/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (2)Versions (5)Used By (0)

lucite/apispec
==============

[](#luciteapispec)

A library for building an mostly unopinionated openapi specifications, with additional functions for building a *strongly* opinionated specification that can be easily connected to other php frameworks.

Unopinionated building blocks
-----------------------------

[](#unopinionated-building-blocks)

The library provides set of classes for defining and connecting various parts of an openapi specification.

For example, you can create a string property named `title` with a minimum length of 10 like this:

`$titleProp = new Lucite\ApiSpec\Property('title', 'string', ['minLength' => 10]);`

You could then add that to a schema named `Employee` like this:

`$schema = (new Lucite\ApiSpec\Schema('Employee'))->addProperty($titleProp);`

The root level of a specification is, unsurprisingly, a `Specification` object:

`$spec = new Lucite\ApiSpec\Specification('myapi', 'v1.1');`

Other classes that are provided:

- `Path`, which can be added to a `Specification` instance.
- `Method`, which can be added to a `Path` instance.
- `PathParameter`, which can be added to a `Method` instance.
- `QueryParameter`, which can be added to a `Method ` instance.
- `Response`, which can be added to a `Method` instance.

While these classes do not allow for the construction of any possible openapi specification, they cover many common cases.

Opinionated structure
---------------------

[](#opinionated-structure)

The `Lucite\ApiSpec\Specification` class has a number of shortcut methods that let you quickly build a highly opinionated API structure.

For a given resource type (say, a Book), one can easily add these 5 routes:

- `GET /books/` which returns an array of zero or more Book resources
- `GET /books/{bookId}` which returns a single Book resource by id
- `POST /books/` which creats a single Book resource
- `PATCH /books/{bookId}` which updates a single Book resource by id
- `DELETE /books/{bookId}` which deletes a single Book resource by id

To build something like this,

```
$bookSchema = (new Lucite\ApiSpec\Schema('Book'))
    ->addProperty(new Property('bookId', type: 'number', primaryKey: true))
    ->addProperty(new Property('title', rules: ['minLength' => 1]))
    ->addProperty(new Property('description'));

$spec = new Lucite\ApiSpec\Specification('testspec', version: '1.2.3');
$spec->addRestMethods('/books/', $bookSchema);
```

### Request format

[](#request-format)

The POST and PATCH methods require a `content-type: application/json` header with a request body containing the following structure:

```
{
  "data": {
    /* schema fields here*/
  }
}
```

### Reponse format

[](#reponse-format)

There are 4 response formats that may be returned from the above routes:

- A successful, single resource response such as:

    ```
    {
        "succeess": true,
        "warnings": {/* object containing warnings */},
        "data": {/* schema properties here*/}
    }
    ```

    This structure is returned from successful requests to: `GET /books/{bookId}`, `POST /books/`, `PATCH /books/{bookId}`
- A successful collection of resources such as:

    ```
    {
        "succeess": true,
        "warnings": {/* object containing warnings */},
        "data": [
      	{/* schema properties here*/},
      	{/* schema properties here*/},
      	{/* schema properties here*/},
        ]
    }
    ```

    This structure is returned from successful requests to: `GET /books/`
- An unsuccessul response such as:

    ```
    {
       "success": false,
       "warnings": {/* object containing warnings */},
       "errors": {/* object containing errors */}
    }
    ```

    This format is returned from `POST /books/` and `PATCH /books/{bookId}` when the request fails.
- An empty response with status code such as:

    - 401 Not Authorized
    - 404 Not Found
    - 204 Deleted

Usage in a framework
--------------------

[](#usage-in-a-framework)

### Writing specification json (yaml not supported)

[](#writing-specification-json-yaml-not-supported)

```
$spec = new Lucite\ApiSpec\Specification('myapi', 'v1.0.0');
# Add schemas, routes, etc to spec

file_put_contents(
    __DIR__.'/spec.json',
    json_encode($spec->finalize()),
);
```

### Looping over routes to add them to an app

[](#looping-over-routes-to-add-them-to-an-app)

Here's an example of how to use a Specification instance to map routes in Lumen or Slim. Other frameworks are probably very similar.

```
$bookSchema = (new Lucite\ApiSpec\Schema('Book'))
    ->addProperty(new Lucite\ApiSpec\Property('bookId', type: 'number', primaryKey: true))
    ->addProperty(new Lucite\ApiSpec\Property('title', rules: ['minLength' => 1]))
    ->addProperty(new Lucite\ApiSpec\Property('description'));

$spec = new Lucite\ApiSpec\Specification('testspec', '1.2.3');
$spec->addRestMethods('/books/', $bookSchema);

$app = something(); # Framework dependent

foreach ($spec->generateRoutes() as $method => $details) {
    [$path, $schemaName, $function] = $details;

    # Lumen framework, requires you to define a class that can be autoloaded
    # via the name Book (you probably want to prepend this with a namespace)
    # with methods getOne, getMany, create, update, delete. Each method
    # should accept params
    # - $args
    # and return a string or array
    # See Lumen framework docs
    $app->$method($path, ['uses' => $schemaName.'Controller@'.$function]);

    # Slim framework, requires you to define a class that can be autoloaded
    # via the name Book (you probably want to prepend this with a namespace)
    # with methods getOne, getMany, create, update, delete. Each method
    # should accept params:
    # - Psr\Http\Message\ServerRequestInterface $request
    # - Psr\Http\Message\ResponseInterface $response
    # - array $args
    # and return Psr\Http\Message\ResponseInterface.
    # See slim framework docs
    $app->$method($path, $schemaName.':'.$function);
}
```

### Using Schema validators

[](#using-schema-validators)

Once a schema is defined, you can create a Lucite\\ApiSpec\\Validator from it. The validator takes an array and returns EITHER:

- a boolean true if the data passes validation
- an associative array of errors

Example:

```
$bookSchema = (new Lucite\ApiSpec\Schema('Book'))
    ->addProperty(new Lucite\ApiSpec\Property('bookId', 'number', primaryKey: true))
    ->addProperty(new Lucite\ApiSpec\Property('title', rules: ['minLength' => 1]))
    ->addProperty(new Lucite\ApiSpec\Property('description'));

$data = ['name' => '']);
$result = $bookSchema->getValidator->validate($data);
# Will return an array containing: ['name' => '{field} must be at least 1 characters long']
```

You can get a validator for a schema from the specification object by schema name:

```
$bookSchema = (new Lucite\ApiSpec\Schema('Book'))
    ->addProperty(new Lucite\ApiSpec\Property('bookId', type: 'number', primaryKey: true))
    ->addProperty(new Lucite\ApiSpec\Property('title', rules: ['minLength' => 1]))
    ->addProperty(new Lucite\ApiSpec\Property('description'));

$spec = new Lucite\ApiSpec\Specification('testspec', '1.2.3');
$spec->addRestMethods('/books/', $bookSchema);
$validator = $spec->getSchema('Book')->getValidator();
```

A good way to use this functionality would be to add the specification object to your dependency injection container, and then -&gt;get() the spec/validator in a controller.

###  Health Score

21

—

LowBetter than 19% of packages

Maintenance36

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity32

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% 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 ~1 days

Total

3

Last Release

596d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/f32209cfa303c34e3216af4d87fccad724cecdc33382165dbd10daede46a262a?d=identicon)[octoth0rpe](/maintainers/octoth0rpe)

---

Top Contributors

[![octoth0rpe](https://avatars.githubusercontent.com/u/31517771?v=4)](https://github.com/octoth0rpe "octoth0rpe (19 commits)")

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/lucite-apispec/health.svg)

```
[![Health](https://phpackages.com/badges/lucite-apispec/health.svg)](https://phpackages.com/packages/lucite-apispec)
```

###  Alternatives

[stripe/stripe-php

Stripe PHP Library

4.0k143.3M480](/packages/stripe-stripe-php)[twilio/sdk

A PHP wrapper for Twilio's API

1.6k92.9M272](/packages/twilio-sdk)[knplabs/github-api

GitHub API v3 client

2.2k15.8M187](/packages/knplabs-github-api)[facebook/php-business-sdk

PHP SDK for Facebook Business

90121.9M34](/packages/facebook-php-business-sdk)[meilisearch/meilisearch-php

PHP wrapper for the Meilisearch API

73813.7M114](/packages/meilisearch-meilisearch-php)[google/gax

Google API Core for PHP

263103.1M454](/packages/google-gax)

PHPackages © 2026

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