Strapi > Let’s extract data from our headless CMS

Andrea Chiumenti
7 min readNov 3, 2023

In the previous article we installed Strapi CMS, we defined a basic model for our data and finally created some record.

It’s now time to extract data and make them available to our application.

Actually there are two options to view these data: we can use RESTful API, or we can choose a more flexible approach using GraphQL.

Both methods have their advantages and peculiarities.

I start by discussing the default approach, which is the RESTful API, and then we will conclude with GraphQL (which is my favorite method for the reasons I’ll explain), and you can choose your preferred method as well.

Instead of guessing out API endpoints, will install our first Strapi extension, in the specific the Documentation extension.

Open a terminal and go to your Strapi install directory.
Then type the following command:

yarn strapi install documentation

Since you should have stated Strapi in development mode with the command `yarn develop`, no restart is necessary because the build system intercepts the mutation as a new dependency has been created and restarts the server for you .

Now go to http://localhost:1337/admin/list-plugins. You will see that Documentation plugin is now present to serve Swagger UI.
Swagger UI is an open-source user interface that allows developers to interact with and visualize the documentation of a RESTful web service and is typically used to display and test the endpoints of a RESTful API.

In another tab of your browser open the following address http://localhost:1337/documentation#/, click on Book item and you will see this page:

Swagger interface shows our endpoints with a padlock icon beside, this means that our API is protected, and without authorization you are not allowed to use it.

Yow need a authorization token.
In the admin console open “Settings”->”Api Tokens” and click on “Add new API token”.

Since for this example you just need to access in read mode the book API, create a “Read-only” token type with duration unlimited

Then click “Save” button and copy the token… and keep in mind this message

Make sure to copy this token, you won’t be able to see it again!

Now back to the Swagger tab and click on the “Authorize” button, then write “Bearer”+ SPACE and paste the token you have just copied.

Authorize and close the dialog.

Open the getter for “books” and just click “Execute”. You will see an output like the following:

{
"data": [
{
"id": 1,
"attributes": {
"Title": "Title 1",
"Description": "Short book description1",
"Author": "ThatsMe",
"ISBN": "123-456",
"LongDescription": "**Long** book description1",
"PublicationDate": "2023-10-19",
"createdAt": "2023-10-19T14:12:49.277Z",
"updatedAt": "2023-10-19T14:12:49.277Z",
"publishedAt": "2023-10-27T13:51:36.148Z"
}
},
{
"id": 2,
"attributes": {
"Title": "Title 2",
"Description": "Short book description2",
"Author": "ThatsMe",
"ISBN": "123-456",
"LongDescription": "**Long** book description2",
"PublicationDate": "2023-10-19",
"createdAt": "2023-10-19T14:14:25.665Z",
"updatedAt": "2023-10-19T14:14:56.673Z",
"publishedAt": "2023-10-27T13:51:36.148Z"
}
},
{
"id": 3,
"attributes": {
"Title": "Title 3",
"Description": "Short book description3",
"Author": "ThatsMe",
"ISBN": "123-456",
"LongDescription": "**Long** book description3",
"PublicationDate": "2023-10-19",
"createdAt": "2023-10-19T14:15:15.068Z",
"updatedAt": "2023-10-19T14:15:37.424Z",
"publishedAt": "2023-10-27T13:51:36.148Z"
}
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 3
}
}
}

Now, you may have noticed that there is no image. Suppose you need the Cover field too. All you need to do is to add to the populate query parameter, comma separated, what you need. In this case “Cover” and the corresponding CURL will be

curl -X 'GET' \
'http://localhost:1337/api/books?populate=Cover' \
-H 'accept: application/json' \
-H 'Authorization: Bearer XXXXXX'

and its result:

{
"data": [
{
"id": 1,
"attributes": {
"Title": "Title 1",
"Description": "Short book description1",
"Author": "ThatsMe",
"ISBN": "123-456",
"LongDescription": "**Long** book description1",
"PublicationDate": "2023-10-19",
"createdAt": "2023-10-19T14:12:49.277Z",
"updatedAt": "2023-10-19T14:12:49.277Z",
"publishedAt": "2023-10-27T13:51:36.148Z",
"Cover": {
"data": {
"id": 1,
"attributes": {
"name": "images1.jpeg",
"alternativeText": null,
"caption": null,
"width": 180,
"height": 280,
"formats": {
"thumbnail": {
"ext": ".jpeg",
"url": "/uploads/thumbnail_images1_1f13b65ee0.jpeg",
"hash": "thumbnail_images1_1f13b65ee0",
"mime": "image/jpeg",
"name": "thumbnail_images1.jpeg",
"path": null,
"size": 5.33,
"width": 100,
"height": 156
}
},
"hash": "images1_1f13b65ee0",
"ext": ".jpeg",
"mime": "image/jpeg",
"size": 11.01,
"url": "/uploads/images1_1f13b65ee0.jpeg",
"previewUrl": null,
"provider": "local",
"provider_metadata": null,
"createdAt": "2023-10-19T14:05:50.600Z",
"updatedAt": "2023-10-19T14:05:50.600Z"
}
}
}
}
},
{
"id": 2,
....

Notice that what you will see, are just the items that you have published, if you need to see items in draft mode, add the following query parameter to the query string: `publicationState=preview`

Now you might object that we are extracting too many fields, suppose that in our list we just need title, description, author and cover.
The relative CURL command should be this:

curl -X 'GET' \
'http://localhost:1337/api/books?populate=Cover&fields[0]=title&fields[1]=description&fields[2]=author&' \
-H 'accept: application/json' \
-H 'Authorization: Bearer XXXXXX'

There are just a pair of annoying problems: Swagger UI at the moment does not support multiple values for parameters like “fields”.
There is no schema for query parameter like fields, populate, filter, etc…, so it’s very easy for a client to obtain a server error

For more info about Strapi RESTful API, visit this address https://docs.strapi.io/dev-docs/api/rest/

Now that you have had a brief glimpse on RESTful API on Strapi I want to show you how working with GraphQL is and why I prefer it over the former method when I work with heterogeneous data such the ones that come from a CMS.

Let’s install “GraphQL” plugin as we have done for “Documentation”

yarn strapi install graphql

Usually, when you install a plugin, you also want to configure it to exactly serve your needs.

In the ./configdirectory create a file named plugins.ts and write the following:

export default {
//
graphql: {
config: {
depthLimit: 7,
amountLimit: 100,
apolloServer: {
tracing: false,
},
},
},
};

amountLimit determines how many records a client can extract, depthLimithow deep you can query an object for its properties.

GraphQL is meant to extract structured data, setting these parameters too high could affect the server performance and could result in a DDoS.

For an in depth list of config options please visit this address https://docs.strapi.io/dev-docs/plugins/graphql

Now visit the GraphQL query console. If you don’t know GraphQL or never used it, I’m pretty sure you will appreciate it.

Open this address http://localhost:1337/graphql in your browser and you will have the following page, that is the GraphQL playground:

Click on the bottom button “HTTP Headers” and add the token you used for RESTful API, or create a new one to use,

Now the funny stuff: query the content.
GraphQL Playground is very easy to use, while you write your query it has a pretty handy autocomplete feature that helps you to write your query (suggestions can also be obtained pressing CTRL+SPACE).

Write the following query on the left and press the play button:

query test_query {
books {
data {
id
attributes {
Title
Description
Author
Cover {
data {
attributes {
formats
}
}
}
}
}
}
}

You should obtain this result

That is exactly what we need, and more concise compared to RESTful result.

Among the advantages of GraphQL over RESTful API is that with just one query you can also ask multiple data in the same request. This is very important for clients because they can obtain what they need in just one request.

For example such a query could be the following (please, it’s just an example, what I’m asking is just to show the query and it doesn’t have a particular meaning :) )

query most_loved_two_books {
book1:book(id:"1") {
data {
attributes {
Title
ISBN
}
}
}
book2:book(id:"3") {
data {
attributes {
Title
ISBN
}
}
}
}

Here I just asked for two books giving the id of the books I was interested into.

GraphQL can also be parametric, let’s now transform the previous query into the following one:

query two_books($first_book:ID, $second_book:ID) {
book1:book(id:$first_book) {
data {
attributes {
Title
ISBN
}
}
}
book2:book(id:$second_book) {
data {
attributes {
Title
ISBN
}
}
}
}

Press the “QUERY VARIABLES” button to edit values for $first_book and $second_book and write:

{
"first_book": "2",
"second_book": "3"
}

Great, we have our custom parametric query!

Of course CTRL+SPACE is not a very reliable way to navigate an API, even if it is very easy to play with.

If you click the vertical button placed on the upper right “DOCS” you will see all the queries and the parameters that you can use:

While if you click on “SCHEMA” you can see how objects are composed:

In the next article I’ll show you how to interface with Strapi and its GraphQL data.

For now it’s all, see you!

Strapi: Headless CMS walk trough

7 stories

--

--

Andrea Chiumenti

Co-founder of Red Software Systems srl — Italy, I’m a software architect with many years of experience in back end and front end development.