How to get _all_ fields I want with Ghost content API?

I’m trying to get a list of posts, but for reasons of limiting data use I only want to get id, title and excerpt fields.

From looking at the examples for the Ghost content API, I should be able to make a call like this

	const options = { fields: 'id,title,excerpt' };
	const posts = await api.posts.browse(options);

but I only get the fields id and title returned to me, not excerpt.

If I add more fields, such as

const options = { fields: 'id,title,excerpt,url,reading_time' };
const posts = await api.posts.browse(options);

again I only get a subset of what I’ve asked for, here id, title, and `url``

How can I get the fields I want? Am I missing something obvious here?

Thanks for any help!

This is due to some limitations with how the API works internally. The excerpt field is generated from the custom_excerpt or plaintext field, if you don’t fetch the custom excerpt and plaintext fields then the excerpt can’t be generated.

So if I do

const options = { fields: 'id,custom_excerpt,excerpt' };
const posts = await api.posts.browse(options);

it should work?

Sorry, I was slightly mistaken with the excerpt case. You’ll need to fetch the plaintext format for the excerpt to be generated.

OK, thanks. What I’m trying to do is get a list of all articles, then have the user click on one and do a second fetch to get just that article. I’m concerned with both the data and speed if I do a fetch of all the articles with plaintext for mobile users. I suppose I could just limit to the first 10 and then move the cursor if I want more, but it’s a shame there’s not a way to avoid the heavy data load of fetching the article in its entirety. Can you suggest a better way I might handle this? Thanks!

How big are your articles? Plaintext is generally tiny and compresses really well, even if you fetch all of the plaintext for all of your articles it’s likely to be less data than a single image. That said, if in doubt, measure :smile:

1 Like

Thanks. No idea how big the articles will be. I’m part of a team that’s evaluating Ghost for the ‘blog’ portion of a large project for an NGO.

Is there a way if you use a limit to set a starting point for the next fetch? One gets the pagination from meta. Then I pass a page field in the options? I don’t see how to set up a cursor using the content API client library (https://ghost.org/docs/api/v3/javascript/content/)

I can get the excerpt:

const options = { fields: 'id,title,excerpt', formats: 'plaintext' };
const posts = await api.posts.browse(options);

One thing I’m having an issue with is that the docs have examples like this

api.posts.read({slug: 'something'}, {formats: ['html', 'plaintext']});

When in fact the API only seems to work if you pass one options object, and the values for fields like format need to be a comma-separated string, not an array of strings. Why are the docs different from what needs to be passed to the API?

@fantasma the Content API SDK docs are correct and match the code. Are you perhaps mixing up .read() and .browse() function arguments?

.read() takes two arguments .read(data, options) where data represents a specific resource ID, eg {id: 'xyz'} or {slug: 'abc'} and options is something like {formats: ['html', 'plaintext']}

.browse() only takes one argument options because there is no specific document ID involved in a browse request.

As for {formats: ['html', 'plaintext']} and {formats: 'html,plaintext'} then either should work, if it’s not working then it’s a bug. You can see in the SDK source code where array params are joined with ',' and associated tests for that functionality.

Is there a way if you use a limit to set a starting point for the next fetch? One gets the pagination from meta . Then I pass a page field in the options?

You can get closer to cursor pagination using dates in the filter param, eg. posts.browse({filter: "created_at:>'2020-02-10 15:45'"}) along with the order and limit param. Though with this approach you’ll need to keep track of the cursor date yourself.

Thanks. You say ‘You can get closer to cursor pagination using dates in the filter param’. What’s the best way to handle pagination with Ghost? I see pagination info in the meta field

 meta: {
    pagination: { page: 1, limit: 15, pages: 1, total: 4, next: null, prev: null }
  }

I would think there’s some ‘accepted Ghost way’ to move through the pages. Is it keeping track of dates? In which case, what purpose does the pagination data serve?

By default the pagination in Ghost uses basic pages, eg posts.browse({page: 1}), posts.browse({page: 2}) etc. Default ordering is published_at desc (most recently published to most distantly published) but you can alter that if needed with the order parameter. The pagination meta data is giving you information about the result set that has just been queried

page: 1,   // requested page
limit: 15, // number of records per page
pages: 4,  // total number of pages available
total: 51, // total number of records
next: 2,   // next page number (null if there's no next page)
prev: null // prev page number (null if there's no previous page)

You can use the meta.pagination.next value to move through pages using the {page: x} param if that’s what you want to do. The other data that’s returned is enough to build a full pagination UI.

There is information about the default pagination in our docs Ghost Content API Documentation

I mentioned dates because you mentioned cursor pagination - that’s typically when you specify a before/after with an optional limit rather than going by page number. For cursor pagination the most typical use case would be to use a date for before/after, but like I said you’d need to keep track of the cursor and generate the before/after values yourself to fit your use case.

2 Likes