API Platform supports the JSON:API format. When a client sends a request with
an Accept: application/vnd.api+json header, API Platform serializes responses following the
JSON:API specification.
For details on enabling formats, see content negotiation.
We recommend configuring API Platform to use entity identifiers as the id field of JSON:API
resource objects. This will become the default in 5.x:
# config/packages/api_platform.yaml
api_platform:
jsonapi:
use_iri_as_id: falseWith this configuration, the JSON:API id field contains the entity identifier (e.g., "10")
instead of the full IRI (e.g., "/dummies/10"). A links.self field is added to each resource
object for navigation:
{
"data": {
"id": "10",
"type": "Dummy",
"links": {
"self": "/dummies/10"
},
"attributes": {
"name": "Dummy #10"
},
"relationships": {
"relatedDummy": {
"data": {
"id": "1",
"type": "RelatedDummy"
}
}
}
}
}Relationships reference related resources by entity identifier and type.
Resources with composite identifiers use a semicolon-separated string as the id value (e.g.,
"field1=val1;field2=val2").
API Platform must resolve the IRI for any resource that appears in a relationship. If a resource has
no standalone GET item endpoint (for example, it is only exposed as a subresource), IRI resolution
fails.
Use the NotExposed operation to register a URI template for internal IRI resolution without
exposing a public endpoint. A NotExposed operation registers the route internally but returns a
404 response when accessed directly:
<?php
namespace App\Entity;
use ApiPlatform\Metadata\NotExposed;
#[NotExposed(uriTemplate: '/tags/{id}')]
class Tag
{
public int $id;
public string $label;
}This allows a parent resource to reference Tag objects in its relationships while Tag itself has
no public item endpoint. The NotExposed operation requires a uriTemplate with a single URI
variable.
The
JSON:API specification allows clients to supply their own id on POST
when the server agrees to accept it. This is useful when the client generates a UUID before sending
the request and needs the server to persist it as-is.
By default, API Platform rejects client-supplied data.id on POST with a 400 response. Enable
it explicitly when needed.
Symfony:
# config/packages/api_platform.yaml
api_platform:
jsonapi:
allow_client_generated_id: trueLaravel (config/api-platform.php):
'jsonapi' => [
'allow_client_generated_id' => true,
],Use the denormalizationContext on the #[Post] operation to enable the feature for a single
endpoint without affecting the rest of the API:
<?php
namespace App\ApiResource;
use ApiPlatform\JsonApi\Serializer\ItemNormalizer;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Post;
#[ApiResource(
formats: ['jsonapi' => ['application/vnd.api+json']],
operations: [
new Get(uriTemplate: '/books/{id}'),
new Post(
uriTemplate: '/books',
denormalizationContext: [ItemNormalizer::ALLOW_CLIENT_GENERATED_ID => true],
),
],
)]
class Book
{
public ?string $id = null;
public string $title = '';
}A request that supplies data.id is then accepted:
POST /api/books HTTP/1.1
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json
{
"data": {
"type": "Book",
"id": "01932b4c-a3f1-7b7e-9e5b-3d8f1c2e4a6d",
"attributes": {
"title": "Hyperion"
}
}
}The supplied id is passed to the entity’s id setter. The processor is responsible for persisting
it. The response output schema still requires id; only the POST input schema marks it as
optional.
You can also help us improve the documentation of this page.
Using an AI coding agent? See the documentation index for LLMs at /docs/llms.txt.
Made with love by
Les-Tilleuls.coop can help you design and develop your APIs and web projects, and train your teams in API Platform, Symfony, Next.js, Kubernetes and a wide range of other technologies.
Learn more