Skip to content

Piece type REST API

Apostrophe provides built-in REST end points for all piece types. The exact document properties returned will depend on the piece type's fields.

Endpoints

Note: :piece-name represents the name of a piece type module. For example, you would request all pieces of an article piece type with /api/v1/article.

REST endpoints

Authentication is required for all requests other than GET requests for pieces with defined publicApiProjection.

MethodPathDescription
GET/api/v1/:piece-nameGet all pieces of a given type, paginated
GET/api/v1/:piece-name/:_idGet a single piece with a specified ID
POST/api/v1/:piece-nameInsert a new piece of the specified type
PUT/api/v1/:piece-name/:_idFully replace a specific piece document
PATCH/api/v1/:piece-name/:_idUpdate only certain fields on a specific document
DELETE/api/v1/:piece-name/:_idPermanently deletes a piece document

Additional piece endpoints

MethodPathDescription
POST/api/v1/:piece-name/:_id/publishPublish the draft version of a piece

This guide will use an article piece type as an example. In addition to standard piece fields, this hypothetical piece type has the following fields (for the sake of illustration):

  • author: a relationship field connected to the user piece type
  • category: a String field
  • body: an area field using the rich text widget.

GET /api/v1/:piece-name

Query parameters

ParameterExampleDescription
page?page=2The page of results to return
search?search=shoesA search query to filter the response
aposMode?aposMode=draftSet to draft to request the draft version of piece documents instead of the current published versions. Set to published or leave it off to get the published version. Authentication is required to get drafts.
aposLocale?aposLocale=frSet to a valid locale to request piece document versions for that locale. Defaults to the default locale.
render-areas?render-areas=trueReplaces area items data with a _rendered property set to a string of HTML based on widget templates.

Custom filters

You may configure custom filters for a piece type as well. See the guide on custom filters for more information.

Request example

javascript
// Request inside an async function.
const response = await fetch('http://example.net/api/v1/article?apikey=myapikey&aposMode=draft', {
  method: 'GET'
});
const document = await response.json();

Response

By default, GET requests return the published and default locale version of each piece.

PropertyTypeDescription
pagesNumberThe total number of pages of results
currentPageNumberThe current page of results
resultsArrayAn array of individual piece objects. See the getOne response for the document structure.
json
  {
    // Total number of pages of results (10 per page by default)
    "pages": 4,
    // The returned page of results
    "currentPage": 1,
    // Piece document results
    "results": [
      {
        "_id": "ckitdo5oq004pu69kr6oxo6fr",
        "archived": false,
        "visibility": "public",
        "type": "article",
        "title": "ES6 and Beyond: modern JavaScript is so worth it",
        "slug": "es6-and-beyond-modern-javascript-is-so-worth-it",
        // ... additional properties
      },
      // ... up to nine additional documents, by default
    ]
  }

In case of an error an appropriate HTTP status code is returned.

GET /api/v1/:piece-name/:_id

Query parameters

ParameterExampleDescription
aposMode?aposMode=draftSet to draft or published to request a specific mode version of the piece. Authentication is required to get drafts.
aposLocale?aposLocale=frSet to a valid locale to request the piece document version for that locale.
render-areas?render-areas=trueReplaces area items data with a _rendered property set to a string of HTML based on widget templates.

INFO

Query parameters will override the locale and mode present in the _id. So, if the aposLocale=es parameter is supplied, a GET request to the _id ###:en:published will return the Spanish, not English, locale. You can also elect to use the aposDocId instead of the _id and use the query parameters to pass in the locale and mode parameters found in the _id.

Request example

javascript
// Request inside an async function.
const response = await fetch('http://example.net/api/v1/article/ckitdo5oq004pu69kr6oxo6fr?apikey=myapikey&aposMode=draft&aposLocale=en', {
  method: 'GET'
});
const document = await response.json();

Response

The successful GET request returns the matching document. See the piece document response example below for a sample response body. In case of an error an appropriate HTTP status code is returned.

POST /api/v1/:piece-name

Query parameters

ParameterExampleDescription
aposMode?aposMode=draftSet to draft to insert a piece as a draft instead of immediately published. Set to published or leave it off to insert a published piece.
aposLocale?aposLocale=frSet to a valid locale to request piece document versions for that locale. Defaults to the default locale.

Request example

javascript
// Object with, at a minimum, properties for each required piece field.
const data = { ... };
// Request inside an async function.
const response = await fetch('http://example.net/api/v1/article?apikey=myapikey', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data)
});
const document = await response.json();

Response

The successful POST request returns the newly created document. See the piece document response example below for a sample response body. In case of an error an appropriate HTTP status code is returned.

PUT /api/v1/:piece-name/:_id

Query parameters

ParameterExampleDescription
aposMode?aposMode=draftSet to draft or published to replace a specific mode version of the piece.
aposLocale?aposLocale=frSet to a valid locale to replace the piece document version for that locale.

Request example

javascript
// Object with, at a minimum, properties for each required piece field.
const data = { ... };
// Request inside an async function.
const response = await fetch('http://example.net/api/v1/article/ckitdo5oq004pu69kr6oxo6fr:fr:published?apikey=myapikey', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data)
});
const document = await response.json();

Response

The successful PUT request returns the newly created document. See the piece document response example below for a sample response body. In case of an error an appropriate HTTP status code is returned.

PATCH /api/v1/:piece-name/:_id

Query parameters

ParameterExampleDescription
aposMode?aposMode=draftSet to draft or published to update a specific mode version of the piece.
aposLocale?aposLocale=frSet to a valid locale to update the piece document version for that locale.

If a PATCH operation is attempted in the published mode, the changes in the patch are applied to both the draft and the current document, but properties of the draft not mentioned in the patch are not published. This is to prevent unexpected outcomes.

Request example

javascript
// Object with *only* the document fields to overwrite.
// This example only changes the article's category to "Nerd Post."
const data = {
  category: 'Nerd Post'
};
// Request inside an async function.
const response = await fetch('http://example.net/api/v1/article/ckitdo5oq004pu69kr6oxo6fr?apikey=myapikey&aposMode=published&aposLocale=en', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data)
});
const document = await response.json();

MongoDB-style requests

The PATCH request body may use MongoDB-style operators. For example, you may use dot or "at" notation to update a nested property:

javascript
{
  // Via "dot notation"
  "description.items.0.content": "<p>Update only the rich text.</p>",
  // Same thing via "@ notation," which finds the nested item with that _id
  "@ckgwegpfw00033h5xqlfb74nk.content": "<p>Update only the rich text.</p>"
}

Response

The successful PATCH request returns the complete patched document. See the piece document response example below for a sample response body. In case of an error an appropriate HTTP status code is returned.

DELETE /api/v1/:piece-name/:_id

Authentication required.

This API route permanently deletes the piece database document. Moving pieces to the archive in the Apostrophe user interface or using a PATCH request to set archived: true do not permanently delete database documents and should be considered.

DELETE requests will be rejected if the _id matches the draft mode of a page that has an existing published mode document.

Query parameters

ParameterExampleDescription
aposMode?aposMode=draftSet to draft or published to delete a specific mode version of the piece.
aposLocale?aposLocale=frSet to a valid locale to delete the piece document version for that locale.

Request example

javascript
// Request inside an async function.
await fetch('http://example.net/api/v1/article/ckitdo5oq004pu69kr6oxo6fr:en:published?apikey=myapikey', {
  method: 'DELETE'
});

Response

The successful DELETE request simply responds with a 200 HTTP response status code. In case of an error an appropriate HTTP status code is returned.

POST /api/v1/:piece-name/:_id/publish

Authentication required.

Publish an existing draft mode document in a document set.

The :_id segment of the route should be one of the following:

  • The _id property of the draft piece to be published
  • The _id property of the published piece to be replaced by the current draft version
  • The aposDocId property of the pieces in the document set

The body of the request is ignored.

Query parameters

ParameterExampleDescription
aposLocale?aposLocale=frIdentify a valid locale to publish the draft for that locale. Defaults to the locale of the _id in the request or the default locale.

Request example

javascript
// Request inside an async function.
const response = await fetch('http://example.net/api/v1/article/ckhdscx5900054z9k88uqs16w:en:draft/publish?apikey=myapikey', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  }
});
const article = await response.json();

Response

The successful POST request returns the newly published piece. See the piece document response example below for a sample response body. In case of an error an appropriate HTTP status code is returned.

Piece document response example

Common properties

PropertyFormatDescription
_idStringA unique and permanent ID for the document
visibilityStringThe visibility setting, controlling public availability
archivedBooleanWhether the document is archived
typeStringThe piece type name
titleStringThe entered title, or name, of the document
slugStringA unique, but changeable, identifier for the piece
createdAtDateAn ISO date string of the document's creation date and time
updatedAtDateAn ISO date string of the document's last update date and time
Content propertiesVariableAdditional properties specific to the piece type and its fields

Example

json
{
  "_id": "ckitdo5oq004pu69kr6oxo6fr",
  "archive": false,
  "visibility": "public",
  "type": "article",
  "title": "ES6 and Beyond: modern JavaScript is so worth it",
  "category": "Tech Tips",
  "slug": "es6-and-beyond-modern-javascript-is-so-worth-it",
  "main": {
    "_id": "ckitdnl9l005t2a681hdgry8r",
    "items": [
      {
        "_id": "ckitdo2fl005x2a68ibiv795n",
        "metaType": "widget",
        "type": "@apostrophecms/rich-text",
        "content": "<p>I'm an old dog. I've been coding the web since 1993. So why do I want to teach you new tricks?</p><p>In 1993 I hopped an Amtrak train from Connecticut to Seattle. Three days of the same designated vegetarian meal. Hoo boy. But the scenery was worth the food.</p><p>And on arrival I discovered two beautiful things: coffee, and Seattle's spoken word scene. Yes, I read slam poetry in dive bars. Very punk rock.</p><p>How did that turn out? Well I was, uh, popular with the critics. Audiences, not so much. Hey, I had fun.</p><p>There was one small problem: I didn't yet have a job.</p><p>Fortunately my former employer at Cold Spring Harbor Laboratory on Long Island called me up one day to ask: \"hey, when you said you could rebuild our cell biology visualization software for this new World Wide Web thing... were you joking?\"</p><p>I quickly decided I wasn't joking. And so I worked remotely from Seattle. Over a 14.4kbps modem. That's <em>way slower than bad 3G</em> for you youngins.</p><p>And so I helped take an application that was limited to a handful of researchers with access to high-end workstations (think \"Unix! I know this\" in Jurassic Park) and bring it to anyone with a decent PC and a modem. <em>Slowly</em>. <em>Barely</em>. But still.</p><p>That was a \"new tricks\" moment. And also a punk rock moment. Something that was difficult and reserved for a priesthood with the relevant skills became that much more accessible.</p><p>&hellip;</p>",
        "_edit": true,
        "_docId": "ckitdo5oq004pu69kr6oxo6fr"
      }
    ],
    "metaType": "area",
    "_edit": true,
    "_docId": "ckitdo5oq004pu69kr6oxo6fr"
  },
  "metaType": "doc",
  "createdAt": "2020-12-17T21:50:45.195Z",
  "updatedAt": "2020-12-21T17:25:34.339Z",
  "updatedBy": {
    "_id": "ckhdsd0hk0003509kchzbdl83",
    "firstName": "Super",
    "lastName": "Admin",
    "username": "admin"
  },
  "authorIds": [
    "ckitdleax002tu69kejca3ho0"
  ],
  "_edit": true,
  "_author": [
    {
      "_id": "ckitdleax002tu69kejca3ho0",
      "archive": false,
      "disabled": false,
      "type": "@apostrophecms/user",
      "firstName": "Tom",
      "lastName": "Boutell",
      "title": "Tom Boutell",
      "slug": "user-tom-boutell",
      "username": "tom",
      "email": "tboutell@example.net",
      "metaType": "doc",
      "createdAt": "2020-12-17T21:48:36.393Z",
      "updatedAt": "2020-12-21T17:25:13.940Z",
      "updatedBy": {
        "_id": "ckhdsd0hk0003509kchzbdl83",
        "firstName": "Super",
        "lastName": "Admin",
        "username": "admin"
      },
      "_edit": true
    }
  ],
  "_url": "http://example.net/blog/es6-and-beyond-modern-javascript-is-so-worth-it",
  "_parentUrl": "http://example.net/blog"
}