This FAQ section is for users currently using Story API NPRML (XML) output who need to migrate over to CDS JSON. Story API is now deprecated as of 2024. All users of Story API are currently being contacted as a reminder to migrate from using Story API queries or plugins to ones backed by CDS.

Differences between Story API (api.npr.org) and CDS

Launched as a public alpha release on June 30 2008, the Story API to this day serves content to many users, primarily stations with custom integrations. It also allows for publishing and sharing content to users.

What will happen to the Story API now that CDS is here?

The Story API is currently slated for retirement in early 2024 (As of the writing of this document). NPR has will continue to support the Story API has a read-only API after that retirement date. Those stations who want to publish content to NPR need to do so either through Grove for Stations or custom integrations that use CDS (Like the Wordpress plugin or Drupal module).

If you are a station or other user migrating from a service using the Story API to one that uses CDS, then this guide is catered for you.

Is there an Allow List in CDS for IP addresses similar to the one used in Story API?

No, there is not. Once you get an API key for CDS, you are all set!

Is there a full text attribute inside of CDS similar to “fullText” from the Story API?

In the Story API we had a notion of “Full Text” versus “normal text” attributes. In CDS we make no distinction between these types. Text will simply have all markup and formatting included.

For more tips like this about fields in Story API versus fields in CDS, see our comprehensive Story API to CDS field guide.

Will there be new IDs for content in CDS versus Story API?

For data that is published and consumed by Story API today, no. However, NPR may change IDs for new content further in the future. These new IDs would only be present in the CDS API.

I’m a user who has content already in CDS that made its way there through Story API ingest. Am I able to edit or delete that content now in CDS?

The short answer is: yes. If you have a CDS Key with an authorizedOrgServiceIds array that contains one or more services in a documents authorizedOrgServiceIds array, then you can edit and delete said document. For more on authentication and how that impacts your permissions in CDS, see the authorization getting started guide here.

Does the CDS have a notion of a story attribution?

Not natively like in the Story API, but the information for making your own attribution. See this guide for making your own attribution similar to Story API’s <div> element.

Story API collections versus CDS Collections

Story API had a more all-in-one approach to querying collections. If you looked up a collection for, say, Animals ID 1132, you only had to go to https://api.npr.org/query?id=1132&apiKey=mykey and you would not only see data on the collection (title, teaser, etc) but also a <list> object containing <story> elements. The story elements represented actual content inside that collection.

For CDS, we lean on using the query API to retrieve items from a collection. Fetching the collection by e.g. /v1/documents/1132 only returns information about the collection as a document and NOT anything about documents attached to that collection. While that may seem complex, it allows for the flexibility of changing a collection parent without having to change all associated children (Which was the case in the Story API).

So how do you do get items from a collection in CDS? Here’s the quick version but see our in-depth query endpoint documentation for more:

/v1/documents?collectionIds=1132&sort=publishDateTime:desc&limit=10

The above would give you the 10 most recently published stories tagged in the Animals collection.

Common Story API queries and their CDS (Or other service) equivalent solution

This section acts as more of a quick solution (“Cookbook”) for common Story API queries converted to modern-day, CDS-backed solutions.

NOTE: All of the Story API examples below are going to show the API path instead of the fully qualified domain name and protocol. We’re also omitting the required apiKey parameter. This is to focus on the query parameters in the examples.

You want an RSS or MediaRSS feed

Old Story API Query: /query?id=1004output=rss,mediaRss,Podcast,podcast

Suggested change: Go to https://feeds.npr.org/1004/rss.xml. This will present you with an RSS output of the same data. 1004 is an example aggregation. To see a list of all aggregations, see The table of aggregations.

You want to find a specific story by id

Story API Query: /query?id={id}

Suggested solution: Use CDS: /v1/documents/{id}

See the documents endpoints guide for more.

You want to search for multiple specific story ids

Story API Query: /query?id=1,2 Suggested solution: Use CDS and the ids parameter: /v1/documents?ids=1,2

For more on querying and all other parameters for querying, including ids, see this guide.

You want to query for items in an aggregation

Story API Query: /query?id={aggId} where aggId is an aggregation (e.g. Topic, Series etc). This returned a list of items representing children of that agg.

Suggested solution: Using collectionIds in CDS Searching for stories in an agg is no longer the same /query?id= param, you must use ?collectionIds. See this querying guide for more information. For a list of relevant CDS aggregations see this table.

You want to choose a specific number of results

Story API Query: /query?numResults={number}

Suggested solution: Use CDS and the limit query parameter: /v1/documents?limit={number}

For more on using limit in querying see this section of the querying guide.

You want to search for only audio stories within an aggregation (e.g. A podcast).

Story API Query: /query?id={aggId}&fields=audio

Suggested solution: Use CDS and query for specific profileIds:

In CDS queries you can use profileIds to ensure certain types of content are returned in the results. There is no support for a fields type parameter as in Story API. In this case, to return content with audio in it, we use the has-audio profile which requires a document have an audio asset.

/v1/documents?profileIds=has-audio&collectionIds=510298

Keep in mind that CDS documents can contain different types of audio. If you are looking for the “main” audio for a story, be sure to use the audio asset that is tagged primary in the audio array:

"audio": [
    {
        "href": "#/assets/5678",
        "rels": ["primary", "headline"]
    }
]

For more on has-audio and audio tagging see this guide.

For more on profiles, see the profiles section.

You want to search for stories from a particular station (295, etc).

Story API Query: /query?orgId={orgId}

Suggested solution: Use CDS and the ownerHrefs query parameter:

/v1/documents?ownerHrefs=https://organization.api.npr.org/v4/services/{serviceId}

For help on finding your Service ID via your Organization ID (orgId) use this URL:

https://organization.api.npr.org/v4/legacy/organizations/{orgId}

The returned results should have a services array including an object with an id value which you use as the serviceId.

For more on querying by ownerHrefs and other parameters see this guide.

You want to filter for dates and sort by dates

Story API Query: /query?sort=dateAsc, query?startDate=yyyy-MM-dd to search through a particular date

Suggested solution: Use the CDS sort parameter with publishDateTime:

Sorts a collection 1004 by date time descending:

/v1/documents?sort=publishDateTime:desc&collectionIds=1004

…Or ascending:

/v1/documents?sort=publishDateTime:asc&collectionIds=1004

Searching via editorial sort (See the querying guide for more information) which places ordered content before unordered content in a collection:

/v1/documents?sort=editorial&collectionIds=1004

For more on querying by date and other methods see this guide.

You want to find assets like images, audio, bylines, etc.

Story API Query: /query?fields=titles,teasers,storyDate,byline,audio,textWithHtml,image,organization,parent,layout

In CDS, all fields are returned on a query. So there is no support for limiting or adding fields via a fields type parameter. profileIds can be used to ensure your query returns documents with certain properties (e.g. Images, Audio or a layout). Below we’re unioning has-audio, renderable and has-images to ensure there is content returned with audio, a layout and images.

/v1/documents?collectionIds=1001&sort=editorial&limit=10&profileIds=has-images&profileIds=has-audio&profileIds=renderable

For more on profiles, see the profiles section.

Within images and audio arrays, there are internal-link objects that are used to link to an asset in the CDS doc and also tag that asset with a semantic meaning. images has a rel enum of primary, promo-* labeled rels and so on. For most story content, you will likely want the promo-* tagged image as that is meant to be the promotional image for a story.

For the audio array, you want to follow the link for the audio asset tagged with the primary rel type in most cases.

For more on the images array see this profile section.

For more on the audio array see this profile section.

You want to track the News aggregation or Top Stories

Story API Query::

/query?numResults=10&id=1001&sort=assigned

Suggested solution: Query using CDS using the collectionIds=1001 parameter with editorial sort and limit:

/v1/documents?collectionIds=1001&limit=10&sort=editorial

For more on querying in CDS see this guide.


© 2025 npr