API Platform Core: hypermedia output and GraphQL from annotated PHP classes
The server component of API Platform: hypermedia and GraphQL APIs in minutes
At a glance
- What is it?
- The library behind the API Platform framework, packaged as a Symfony bundle, with content negotiation across JSON-LD, Hydra, HAL, JSON:API and Problem Details. The interesting engineering is in the release notes, where two major versions shipped on the same afternoon.
- Who is it for?
- API Platform Core is the piece to evaluate if you care about the response format rather than the scaffolding, since a working API is a matter of annotating classes and registering the bundle, with no installer involved. The catch is that you inherit a framework's worth of opinionated behaviour about identifiers, relations, pagination and error shapes, and overriding it is documented as possible rather than easy.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 8, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A library you install, not a project you generate
The distinction from the installer repository is the first thing to get straight. API Platform Core is a Composer library distributed as a Symfony bundle, and the README describes it as a component of the API Platform framework that integrates with Symfony through that bundle. You add it to an existing application with Composer and register a bundle class. There is no generator, no template directory, and nothing about your project layout beyond what Symfony already expects.
What you get in return is described in two short paragraphs. It creates hypermedia-driven REST and GraphQL APIs, and it natively supports JSON-LD, the Hydra Core Vocabulary, OpenAPI v2 and v3, JSON:API, HAL and RFC 7807 Problem Details. The stated ambition is a working, fully featured web API in minutes, with the ability to extend or override anything.
The framing as a component also tells you where the complexity lives. This is not a small package that wraps Doctrine and serialises entities. It maintains metadata about your classes, generates documentation from that metadata, and negotiates between several document formats on the same route. That is a lot of machinery, and it is the machinery the release notes spend their time on.
Hypermedia formats are the reason this library is different
Supporting six output formats from one data model is the feature that distinguishes API Platform Core from an ordinary Symfony serializer. Content negotiation means the same endpoint can return JSON-LD with a Hydra context, plain JSON:API, HAL, or an OpenAPI document depending on what the client asks for or which route it calls.
Each of those formats makes different demands. JSON-LD requires a context document so a client can resolve terms, which is why the repository contains a standalone script, `update-hydra-context.php`, at its root. Hydra adds vocabulary on top of JSON-LD to describe collections and controls, such as pagination and filtering affordances. HAL is link-oriented and lighter. JSON:API is a specification with a strict envelope around resources, which is why the release notes contain a fix for using the serialized key for client-generated ids in JSON:API.
That last point is a good illustration of the maintenance cost of the promise. Supporting a format properly means tracking its specification, and a fix titled `fix(jsonapi): use the serialized key for client-generated ids` in v4.4.2 is exactly the kind of change that only exists because the library takes the specification seriously. If you only need JSON, the breadth is overhead you are paying for.
Two maintained lines patched on the same afternoon
The three most recent releases are v5.0.1 published on 2026-09-25, v4.4.2 on 2026-09-25 and v4.3.20 on 2026-09-25. Two version lines receiving patch releases within the same hour is the single most useful fact for anyone deciding what to pin.
It tells you the v4 line is still maintained rather than abandoned, which matters if you already run v4. It also tells you the v5 line is young enough that its first patch release is still collecting small fixes, and one of those fixes is telling: strict query parameter validation was rejecting pagination parameters, and the validator was emitting an unresolved `{{ type }}` placeholder. Both shipped in v5.0.1.
The rest of the v5.0.1 list is infrastructure work. The deprecated option in an error message is now named so you can tell what to change, XML OpenAPI parameters are serialised as a list, user metadata takes precedence over filter documentation in the OpenAPI output, and a batch of test changes aligns the suite with PHPUnit 13 while replacing a deprecated test case class. The v4.4.2 list is similar and includes hiding the GraphiQL link when GraphQL is disabled, attaching a provider for class-string filters, resolving URI variable identifiers from metadata, and migrating the Mercure tests to protocol 1.0.
What the repository tree says about how the project is built
The tree is conventional for a mature Symfony component and tells you where to look. `src/` holds the library, `tests/` the test suite, `tools/` helper scripts, and `docs/` the documentation sources alongside the `Caddyfile` used to serve them locally. There is an `AGENTS.md` for automated contributors, a `CHANGELOG.md`, and a `CONTRIBUTING.md`.
The quality tooling is extensive and worth noting because it tells you what the maintainers consider non-negotiable. `phpstan.neon.dist` for static analysis, `phpunit.xml.dist` with a `phpunit.baseline.xml` alongside it, `codecov.yml` for coverage reporting, and `pmu.baseline` for mutation testing. There is also a `.php-cs-fixer.dist.php` for code style and a `.commitlintrc` that enforces commit message format. A mutation testing baseline is unusual and suggests the project is defended against tests that pass without asserting anything.
On the JavaScript side there is a `package-lock.json` and, more unusually, `.redocly.yaml` with a `.redocly.lint-ignore.yaml` beside it. That is the Redocly configuration for linting OpenAPI documents, which tells you the library's output is validated as a specification rather than merely generated. There is no `.git` directory hint of a monorepo; `composer.json` sits at the root next to `package-lock.json`, so the PHP package and the documentation tooling live side by side.
Where the abstraction starts to cost you
The honest limitation is that metadata-driven frameworks optimise for the case where your domain model is stable. API Platform Core builds behaviour from metadata attached to your classes: identifiers, relations, filters, ordering and the documentation that describes them. That is fast when a resource maps cleanly to a table and awkward when it does not.
Two categories of friction follow. The first is identifiers and relations. The release notes include fixes for Doctrine watching new relations for assigned ids by reference, and for resolving URI variable identifiers from metadata. Both are the same problem seen from different ends: deciding what a relation's id is before the related object has been persisted.
The second is validation. The v5.0.1 fix for strict query parameter validation rejecting pagination parameters shows a strictness that is generally desirable and occasionally in your way, and the risk of it is that the strictness applies to query parameters you did not think of as validated at all.
There is also a GraphQL-specific wrinkle in the fixes. Nullable input fields with a default value were changed in v4.4.2, and the GraphiQL link is now hidden when GraphQL is disabled, which implies GraphQL can be turned off independently of the REST side. Anyone running both surfaces will spend time reconciling two schemas that the framework derives from the same classes but does not keep perfectly in step.
Model Context Protocol support and the shape of current work
One fix in v4.4.2 is worth isolating because it says where the project is heading: `fix(mcp): fix ignored output format`. Whatever else the bundle does, it now has a path where a requested output format was being dropped in some MCP context, which implies MCP is a supported consumption surface rather than an experiment.
That sits oddly next to the rest of the release work, which is a careful maintenance pass on specifications: OpenAPI v2 and v3 both remain supported alongside JSON:API, HAL, Hydra and Problem Details, and the Redocly linting configuration in the repository is there to keep the OpenAPI output honest. The project is holding a wide compatibility surface while adding a new one.
For an evaluator, that combination argues for checking what you actually need rather than what you could use. If your consumers are internal frontends, plain JSON from Doctrine entities is the whole requirement and the format breadth is unclaimed value. If you are publishing linked data or you have clients that need OpenAPI to be specification-valid, the breadth is the reason to choose this library.
The project is MIT licensed, the `LICENSE` file is at the root, and the repository is not archived with the last push on 2026-09-28. Documentation lives at api-platform.com/docs/core, and the README is explicit that it is there rather than in the repository.
Editorial conclusion
API Platform Core is the piece to evaluate if you care about the response format rather than the scaffolding, since a working API is a matter of annotating classes and registering the bundle, with no installer involved. The catch is that you inherit a framework's worth of opinionated behaviour about identifiers, relations, pagination and error shapes, and overriding it is documented as possible rather than easy. Two things to check before starting: whether v5 or the v4 line is the right target given both were patched on 2026-09-25, and how the JSON-LD context handling in `update-hydra-context.php` fits an existing public API you cannot reshape. Read the docs at api-platform.com/docs/core, install the bundle from Composer, and try one resource class with two formats before committing the whole domain model.
Frequently asked questions
What is API Platform Core?
It is the library behind the API Platform framework, distributed as a Symfony bundle for building hypermedia REST and GraphQL APIs. It natively supports JSON-LD, the Hydra vocabulary, OpenAPI v2 and v3, JSON:API, HAL and Problem Details, and it is added to an existing project with Composer rather than used to generate one.
Which version of API Platform Core should a new project use?
The v5 line is the current major version, and its first patch release, v5.0.1, shipped on 2026-09-25. The v4 line is still receiving patches, with v4.4.2 and v4.3.20 released the same day, so an existing v4 project is not being abandoned and can pin that line instead.
Which output formats does API Platform Core support?
The README lists JSON-LD, the Hydra Core Vocabulary, OpenAPI v2 formerly known as Swagger and v3, JSON:API, HAL and Problem Details from RFC 7807. Supporting several of these at once is why the repository ships an `update-hydra-context.php` script for the linked data context and a Redocly configuration for linting OpenAPI output.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/api-platform-core)