import QsForQueryBody from '/docs/snippets/qs-for-query-body.md'
REST API: status#
The REST API's status parameter returns either published versions (default) or drafts by passing status=draft.
It also applies to write requests: a POST or PUT request publishes immediately unless you pass status=draft.
The REST API offers the ability to work with the draft or the published version of documents through the status parameter:
published: targets the published version of documents (default)draft: targets the draft version of documents
The Draft & Publish feature should be enabled.
To select documents by how their draft and published versions relate (never-published, modified, and others), see REST API: publicationFilter.
Read draft or published versions {#read}#
Add the status parameter to a GET request to choose which version is returned.
curl 'http://localhost:1337/api/restaurants?status=draft' \
-H 'Authorization: Bearer <token>'
const qs = require('qs');
const query = qs.stringify({
status: 'draft',
}, {
encodeValuesOnly: true, // prettify URL
});
await request(`/api/restaurants?${query}`);
{
"data": [
{
"id": 5,
"documentId": "znrlzntu9ei5onjvwfaalu2v",
"Name": "Biscotte Restaurant",
"Description": [
{
"type": "paragraph",
"children": [
{
"type": "text",
"text": "This is the draft version."
}
]
}
],
"createdAt": "2024-03-06T13:43:30.172Z",
"updatedAt": "2024-03-06T21:38:46.353Z",
"publishedAt": null,
"locale": "en"
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 1
}
}
}
Populate draft or published relations {#populate}#
The status parameter applies to the whole request, including populated relations. Populated relations return the version requested with status when their content-type has Draft & Publish enabled:
- Without
status, or withstatus=published, populated relations return their published versions. Related documents that were never published are left out. - With
status=draft, populated relations return their draft versions, including related documents that were never published.
The same rule applies at every population level, including relations populated inside components and dynamic zones. Populated relations follow status even when the queried content-type has Draft & Publish disabled.
status is only accepted at the root of the query. Adding it inside a populate object, such as populate[categories][status]=draft, returns a 400 error with a message such as Invalid key status at categories.
Because status applies to the whole request, a single request cannot return published documents with draft relations, or the opposite. Filtering populated relations on publishedAt does not change this: it only narrows down the versions selected by the root status. Send 1 request per status instead.
The publicationFilter parameter follows the same rules. It is only accepted at the root of the query, and Strapi filters populated relations with the same value.
In the following example, the restaurant and its category are both returned as drafts, so publishedAt is null for both:
curl 'http://localhost:1337/api/restaurants?status=draft&populate=categories' \
-H 'Authorization: Bearer <token>'
const qs = require('qs');
const query = qs.stringify({
status: 'draft',
populate: 'categories',
}, {
encodeValuesOnly: true, // prettify URL
});
await request(`/api/restaurants?${query}`);
{
"data": [
{
"id": 5,
"documentId": "znrlzntu9ei5onjvwfaalu2v",
"Name": "Biscotte Restaurant",
"createdAt": "2024-03-06T13:43:30.172Z",
"updatedAt": "2024-03-06T21:38:46.353Z",
"publishedAt": null,
"locale": "en",
"categories": [
{
"id": 8,
"documentId": "z0y2x4w6v8u1t3s5r7q9onm",
"name": "French cuisine",
"createdAt": "2024-03-06T13:40:12.004Z",
"updatedAt": "2024-03-06T13:40:12.004Z",
"publishedAt": null,
"locale": "en"
}
]
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 1
}
}
}
Create or update as a draft or as published {#create-update}#
The status parameter also applies to POST and PUT requests, where it determines whether the document is left as a draft or published right away:
| Request | Result |
|---|---|
POST /api/:pluralApiId?status=draft | Creates a draft document |
POST /api/:pluralApiId | Creates a document and publishes it immediately |
PUT /api/:pluralApiId/:documentId?status=draft | Updates the draft without publishing the changes |
PUT /api/:pluralApiId/:documentId | Updates the draft and publishes it |
PUT /api/:pluralApiId/:documentId with an empty data object | Publishes the draft as-is, without changing its content |
The same applies to single types, where the status parameter can be passed to PUT /api/:singularApiId.
Create a draft {#create-draft}#
curl -X POST \
'http://localhost:1337/api/restaurants?status=draft' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"data": {
"Name": "Biscotte Restaurant"
}
}'
const response = await fetch(
'http://localhost:1337/api/restaurants?status=draft',
{
method: 'POST',
headers: {
Authorization: 'Bearer <token>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: {
Name: 'Biscotte Restaurant',
},
}),
}
);
const data = await response.json();
{
"data": {
"id": 13,
"documentId": "jae8klabhuucbkgfe2xxc5dj",
"Name": "Biscotte Restaurant",
"createdAt": "2024-03-06T22:19:54.646Z",
"updatedAt": "2024-03-06T22:19:54.646Z",
"publishedAt": null,
"locale": "en"
},
"meta": {}
}
The publishedAt field is null, which confirms the document was created as a draft.
Create and publish immediately {#create-published}#
Omitting the status parameter, or passing status=published, creates the document and publishes it in a single request:
curl -X POST \
'http://localhost:1337/api/restaurants' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"data": {
"Name": "Biscotte Restaurant"
}
}'
const response = await fetch(
'http://localhost:1337/api/restaurants',
{
method: 'POST',
headers: {
Authorization: 'Bearer <token>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: {
Name: 'Biscotte Restaurant',
},
}),
}
);
const data = await response.json();
{
"data": {
"id": 13,
"documentId": "jae8klabhuucbkgfe2xxc5dj",
"Name": "Biscotte Restaurant",
"createdAt": "2024-03-06T22:19:54.646Z",
"updatedAt": "2024-03-06T22:19:54.646Z",
"publishedAt": "2024-03-06T22:19:54.649Z",
"locale": "en"
},
"meta": {}
}
Here publishedAt holds a timestamp instead of null, which confirms the document was published.
Update a draft without publishing it {#update-draft}#
Pass status=draft to a PUT request to modify the draft version and leave the published version untouched:
curl -X PUT \
'http://localhost:1337/api/restaurants/jae8klabhuucbkgfe2xxc5dj?status=draft' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"data": {
"Name": "Biscotte Restaurant (closed)"
}
}'
const response = await fetch(
'http://localhost:1337/api/restaurants/jae8klabhuucbkgfe2xxc5dj?status=draft',
{
method: 'PUT',
headers: {
Authorization: 'Bearer <token>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: {
Name: 'Biscotte Restaurant (closed)',
},
}),
}
);
const data = await response.json();
{
"data": {
"id": 13,
"documentId": "jae8klabhuucbkgfe2xxc5dj",
"Name": "Biscotte Restaurant (closed)",
"createdAt": "2024-03-06T22:19:54.646Z",
"updatedAt": "2024-03-06T22:24:12.145Z",
"publishedAt": null,
"locale": "en"
},
"meta": {}
}
Publish an existing draft {#publish-later}#
To publish a draft created earlier, send a PUT request without the status parameter, or with status=published:
curl -X PUT \
'http://localhost:1337/api/restaurants/jae8klabhuucbkgfe2xxc5dj' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"data": {
"Name": "Biscotte Restaurant (closed)"
}
}'
const response = await fetch(
'http://localhost:1337/api/restaurants/jae8klabhuucbkgfe2xxc5dj',
{
method: 'PUT',
headers: {
Authorization: 'Bearer <token>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: {
Name: 'Biscotte Restaurant (closed)',
},
}),
}
);
const data = await response.json();
{
"data": {
"id": 13,
"documentId": "jae8klabhuucbkgfe2xxc5dj",
"Name": "Biscotte Restaurant (closed)",
"createdAt": "2024-03-06T22:19:54.646Z",
"updatedAt": "2024-03-06T22:26:38.902Z",
"publishedAt": "2024-03-06T22:26:38.905Z",
"locale": "en"
},
"meta": {}
}
A PUT request requires a data object in the body, so the request above updates and publishes in a single operation.
Publish a draft without changing its content {#publish-unchanged}#
To publish a draft as-is, send a PUT request with an empty data object:
curl -X PUT \
'http://localhost:1337/api/restaurants/jae8klabhuucbkgfe2xxc5dj' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"data": {}
}'
const response = await fetch(
'http://localhost:1337/api/restaurants/jae8klabhuucbkgfe2xxc5dj',
{
method: 'PUT',
headers: {
Authorization: 'Bearer <token>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: {},
}),
}
);
const data = await response.json();
{
"data": {
"id": 13,
"documentId": "jae8klabhuucbkgfe2xxc5dj",
"Name": "Biscotte Restaurant (closed)",
"createdAt": "2024-03-06T22:19:54.646Z",
"updatedAt": "2024-03-06T22:26:38.902Z",
"publishedAt": "2024-03-06T22:31:14.207Z",
"locale": "en"
},
"meta": {}
}