All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.0.0-rc.1 - 2026-01-01
- Replace
Resource::getId(object $model, Context $context): stringmethod withResource::id(): Idmethod, which returns anIdfield instance to define ID schema, validation, and writability - Change
ErrorProvider::getJsonApiErrors(): arraytoErrorProvider::getJsonApiError(): array(singular) - exceptions now represent a single error rather than potentially multiple errors. WrapErrorProvidersinJsonApiErrorsExceptionto represent multiple errors. - Rename
Exception\Concerns\SingleErrortrait toException\Concerns\JsonApiErrorand change its API:setSource(?array $source): static→source(array $source): staticsetMeta(?array $meta): static→meta(array $meta): staticsetLinks(?array $links): static→links(array $links): static
- Custom deserializers on
ToOnerelationships now receive the resolved model rather than the raw relationship object, for consistency withToMany - Remove
Pagination\Concerns\BuildsUrlstrait (replaced byContext::currentUrl()) - Move
Extension\AtomictoExtension\Atomic\Atomic - Remove
json_api_response()helper (useContext::createResponse()instead) - Remove
Context::queryParam()(useContext::parameter()for defined parameters, orContext::$request->getQueryParameters())
- Major refactor of endpoints, query parameter validation, and OpenAPI schema
generation
- Allow endpoints and pagination implementations to define query parameters for validation and schema generation
- Allow endpoints to define resource and relationship links
- Introduce
SchemaContextto store relevant context during schema generation - Make
ShowandUpdateaggregate separate*Resourceand*Relationshipendpoints - Refactor endpoint handlers and traits
- More comprehensive type schema support
- Add
nullable()method toTypeclasses, allowing sub-types (e.g. array items or object properties) to be nullable - Add
Obj,Any,AnyOf,AllOf,OneOf, andNottypes - Convert type validation errors to overridable exception classes
- Add
- Add
Context::createResponse()method for building JSON:API responses with automaticjsonapiobject inclusion - Add
JsonApi::meta()method for including meta information in thejsonapiobject - Add support for resource links:
- Add
Resource::links()method for defining custom resource-level links - Add
Schema\Linkclass for defining rich link objects with metadata
- Add
- Add
Page::$rangeTruncatedparameter for cursor pagination range truncation support - Add full support for JSON:API profiles:
- Parse profile URIs from
Acceptheader Context::profileRequested(string $uri): bool- check if a profile was requestedContext::requestedProfiles(): array- get all requested profile URIsContext::activateProfile(string $uri)- activate a profile for the responseContent-Typeheader- Cursor pagination automatically activates the
https://jsonapi.org/profiles/ethanresnick/cursor-paginationprofile
- Parse profile URIs from
- Add support for asynchronous processing following the
JSON:API Asynchronous Processing
recommendation
- Add
Create::async()method for responding with202 Accepted - Add
Show::seeOther()method for responding with303 See Otherredirects
- Add
- Add endpoint hooks for customizing responses and schema:
- Add
Endpoint::headers()method for defining custom response headers withHeaderschema class - Add
Endpoint::response()method for defining custom response callbacks - Add
Endpoint::schema()method for defining custom schema - Add
Create::saved()andUpdate::saved()to register callbacks after the model/fields are saved, but before the response is serialized
- Add
- Add ability to customize error objects
- Add specific exception classes for all errors
- Add
JsonApi::errors(array $overrides)method to register error object overrides, keyed by exception class name.detailvalues accept replacements using the:keysyntax. - Add
Exception\JsonApiErrorsExceptionfor representing multiple errors
- Add
Context::currentUrl(array $params = []): stringmethod for building URLs with query parameter overrides - Add
selflink toIndexendpoint document - Add
Idfield class for customizing resource ID behavior, including:- Type constraints (string, integer, etc.)
- Client-generated IDs via
writableOnCreate() - Custom validation rules
- Getter/setter callbacks
- Add
linkageMeta()method to relationship fields for adding meta to resource identifier objects in linkage - Add static
Field::location(): stringmethod to determine where fields appear in JSON:API documents (attributes,relationships, or root level forid) - Add
Context::$datato access resolved create/update data in callbacks
- Various performance optimizations to improve serialization speed
- Improve OpenAPI schema generation to properly handle ID field constraints and avoid redundant properties
1.0.0-beta.6 - 2025-10-02
- Change
Resource\Paginatable::paginate()signature to accept the resolved offset and limit integers (plus the request context) and return the page of results instead of mutating the query in place - New contract for custom
Paginationimplementations:- Add
paginate(object $query, Context $context): Pagemethod which should return a page of results - Remove
metaandlinksmethods; set this data inpaginatevia theContextobject
- Add
Resource\\Listableimplementations must now providedefaultSort()andpagination()methods so defaults can be reused when listing related data- Refactor
Serializerso it is instantiated without aContextand expects the resource context to be provided toaddPrimary()/addIncluded()
- Add cursor pagination support via
Endpoint\Index::cursorPaginate()and theResource\CursorPaginatablecontract, following theethanresnick/cursor-paginationJSON:API profile - Allow exceptions to attach
metaandlinksmembers to the error response - Add
Context::$documentMetaandContext::$documentLinksasArrayObjectinstances to allow callbacks to add meta information to the response document - Support JSON:API relationship URLs via the
Showendpoint, adding automaticself/relatedlinks, and paginated/filterable/sortable to-many responses when the related resource isListable - Allow the
Updateendpoint to handlePATCH/POST/DELETErequests to relationship URLs and return the updated relationship document - Implement the
Resource\Attachablecontract and addToMany::attachable(),validateAttach(), andvalidateDetach()helpers for controlling relationship mutation endpoints with attach/detach hooks - Introduce
Endpoint\ProvidesResourceLinksandEndpoint\ProvidesRelationshipLinksso endpoints can contribute relationship and resource links during serialization
1.0.0-beta.5 - 2025-09-27
Tobyz\JsonApiServer\Laravel\Filter\EloquentFilterrenamed toColumnFilter- Remove the
HasLaravel filter; useWhereExistsinstead - Remove the
WhereDoesntHaveLaravel filter; use the operator support onWhereHasinstead - Remove
Where::asNumber(); express numeric comparisons with operators such asfilter[score][gt]=...orfilter[score][lte]=...
- Add support for boolean filter groups (
filter[and],filter[or],filter[not]) for resources that implement theSupportsBooleanFiltersinterface - Laravel: Add support for boolean filter groups to
EloquentResource - Laravel: Overhaul filter implementations to support operators like
eq,ne,in,lt,lte,gt,gte,like,notlike,null, andnotnull
1.0.0-beta.4 - 2025-05-02
- Add support for generating OpenAPI Definitions
- Add
CollectionActionandResourceActionendpoints - Allow including relationships by default (#96 by @SychO9)
- Add support for conditional linkage (#110 by @SychO9)
- Add
Enumsupport toStrtype - Add the ability to make a field
sparseby default - Add the ability to add
aftercallbacks to theCreateendpoint - Add the ability to pass a condition to
writableOnCreate - Add
Relationship::notIncludable() - Allow
psr/http-messagev2 - Laravel: Add
ToOneandToManysubclasses which support constraining relationship queries (#103 by @SychO9) - Laravel: Support array of abilities in
canhelper
- Laravel:
EloquentCollectionqueries now keep the resource'sEloquent\Builderinstead of converting to the baseQuery\Builder - Laravel: Apply
EloquentResourcescope when applyingWhereHasfilter
- Fix error when request body
data.attributesis null (#98 by @SychO9) - Fix support for nested includes on polymorphic relationships
- Fix
multipleOfbugs (#114 by @bertramakers) - Fix error when using
Context::withRequest(#107 by @SychO9) - The
selflink for a resource now only appears if theShowendpoint is present in a collection - Laravel: Support dynamically resolved relationships (#100 by @SychO9)
- Laravel: Fix serialization for
MorphTorelationships (#97 by @SychO9) - Laravel: Only attempt to preload related
EloquentResources - Laravel: Fix error parameter name in
WhereBelongsTofilter - Laravel: Fix limiting
ToManyrelation results (#112 by @SychO9)
1.0.0-beta.3 - 2023-12-09
- Drop
Interfacesuffix from various interfaces:Resourceclass renamed toAbstractResourceResourceInterfacerenamed toResourceCollectionInterfacerenamed toCollectionErrorProviderInterfacerenamed toErrorProviderPaginationInterfacerenamed toPaginationEndpointInterfacerenamed toEndpointTypeInterfacerenamed toType
- Call user-defined serializer before type serializer (#91)
- Fix finding resource when creating polymorphic relationship (#93)
- Prevent relationship value from being retrieved if it won't be used (not included and no linkage)
1.0.0-beta.2 - 2023-12-02
- Types are now their own construct instead of being subclasses of
Attribute. See the Attributes documentation for more information. - Removed support for defining polymorphic relationships by passing a map of model classes to resource types. You should use heterogeneous collections instead. See the Relationships documentation for more information.
- Add support for heterogeneous collections
- Add
Arrtype for defining array attributes (#88 by @bertramakers) - Laravel: Allow
WhereHasfield to be specified manually
- When creating a resource, set the context model prior to field validation
- Fix error when updating a resource with a conflicting ID (#85)
- Laravel: Fix
Hasfilter not working without ascope - Laravel: Don't apply relationship loading constraints if there aren't any
1.0.0-beta.1 - 2023-09-24
- Add
Str::enum()method (#75 by @bertramakers) - Allow literal values in
Field::default()method (#80 by @bertramakers)
- Fix
Numberproperties not being initialized - Fix validators not being run for null values
- Fix
DateTimevalues containing milliseconds not being accepted - Fix nested filters not receiving correct resource in context
- Laravel: Fix
EloquentResourcesometimes using incorrect relation name when setting value - Laravel: Convert
DateTimevalues to Laravel app's storage timezone - Laravel: Validate that
WhereBelongsTofilter input is a list
1.0.0-alpha.2 - 2023-08-19
- Finish Laravel integration
- Add basic field schema configuration in preparation for OpenAPI generation
- Add
Context::$queryto access the query used in theIndexendpoint - Add
Context::fieldRequested()andContext::sortRequested()methods - Add
BooleanDateTimeattribute for exposing internal date-time values as booleans - Improve error sources in Bad Request errors
- Add a performance benchmark
- Add
voidreturn type toFilter::apply()signature
- Fix typed attribute values being deserialized and always passing validation
- Fix visibility callback result not being cast to a boolean
- Fix
Integerincorrectly not extendingNumber - Fix empty to-many relationships not being present in the response at all
- Fix TypeError when removing non-nullable to-one relationship (#74 by @bertramakers)
1.0.0-alpha.1 - 2023-06-21
-
New class-based API. More ergonomic for managing large resource definitions and inheriting/overriding behavior. Complex fields can be extracted into their own classes and reused across resources.
-
Typed attributes. Implementations of typed attributes are provided to match the data types in the OpenAPI specification. Attributes can be marked as required and nullable.
-
Customizable endpoints. Each endpoint is now opt-in for each resource and can be configured and implemented separately. Also adds the ability for custom endpoints to be added.
-
Restructured internals. The codebase is cleaner and easier to reason about, especially the serialization process.
Still to come:
- Implementation of Laravel stuff (currently it is documented but not implemented)
- Ability to generate OpenAPI definitions
- Additional attribute types (array, object)
- Benchmarks
0.2.0 - 2022-06-21
- Fix
EloquentAdapter::filterByIds()getting key name from query model instead of adapter model - Fix deprecation notice on PHP 8.1
0.2.0-beta.6 - 2022-04-22
- Add support for
doctrine/inflector:^2.0
0.2.0-beta.5 - 2022-01-03
Context::getBody()method to retrieve the parsed JSON:API payload from the requestContext::sortRequested()method to determine if a sort field has been requested
Laravel\rules(): Fix regression disallowing use of advanced validation rules like callbacks andRuleinstances. (@SychO9)
0.2.0-beta.4 - 2021-09-05
Laravel\rules(): Replace{id}placeholder in rules with the model's key.- This is useful for the
uniquerule, for example:unique:users,email,{id}
- This is useful for the
Laravel\can(): Pass through additional arguments to Gate check.- This is needed to use policy methods without models, for example:
can('create', Post::class)
- This is needed to use policy methods without models, for example:
- Get a fresh copy of the model to display after create/update to ensure consistency
- Respond with
400 Bad Requestwhen attempting to filter on an attribute of a polymorphic relationship
0.2.0-beta.3 - 2021-09-03
- Fix dependency on
http-acceptnow that a version has been tagged - Change
EloquentAdapterto load relationships usingloadinstead ofloadMissing, as they may need API-specific scopes applied
0.2.0-beta.2 - 2021-09-01
- Content-Type validation and Accept negotiation
- Include
jsonapiobject withversionmember in response - Validate implementation-specific query parameters according to specification
- Added
Locationheader to201 Createdresponses - Improved error responses when creating and updating resources
Context::filter()method to get the value of a filterResourceType::applyScope(),applyFilter()andapplySort()methodsResourceType::url()method to get the URL for a modelForbiddenerror details for CRUD actions, useful when running Atomic OperationsJsonApi::getExtensions()method to get all registered extensionsConflictExceptionclass
- Renamed
$linkageparameter inAdapterInterfacemethods to$linkageOnly - Renamed
Type::newModel()tomodel()to be consistent with Adapter
- Properly respond with meta information added to
Contextinstance
0.2.0-beta.1 - 2021-08-27
- Preliminary support for Extensions
- Support filtering by nested relationships/attributes (eg.
filter[relationship.attribute]=value) - Add new methods to Context object:
getApi,getPath,fieldRequested,meta - Eloquent adapter: apply scopes when including polymorphic relationships
- Laravel validation helper: support nested validation messages
- Allow configuration of sort and filter visibility
- Add new
setIdmethod toAdapterInterface
- Change paradigm for eager loading relationships; allow fields to return
Deferredvalues to be evaluated after all other fields, so that resource loading can be buffered. - Remove
onprefix from field event methods
- Removed
loadanddontLoadfield methods
- Fix pagination next link appearing when it shouldn't