NAV
Examples

Flyway Integration API

Welcome to the Flyway Integration API! To integrate your content management system with Flyway you first need to implement this API.

Introduction

This API exposes articles, galleries and dependent entities in a consistent manner that should enable smooth migration into Copilot. It is based quite extensively on the Copilot API (you need to be on the Conde Nast VPN to view this link) to ensure consistent naming and simplify the diagnosis of any migration failures.

We have usage examples using curl in the shell.

This API documentation page was created with Slate.

Authentication

To protect your Integration API from abuse, you may wish to implement IP based restrictions (also known as whitelisting). To facilitate this, the IP addresses of the relevant Flyway Services can be made available upon request.

REST Principles

The API closely approximates all of the basic tenets of REST:

The standard set of HTTP status codes to indicate successes, failures, and errors.

Hypermedia

e.g. the self, next and prev properties from the second page of all articles:

{
  // Snip ...
  "self": "https://flyway-api-demo.example.com/api/articles?page=2",
  "next": "https://flyway-api-demo.example.com/api/articles?page=3",
  "prev": "https://flyway-api-demo.example.com/api/articles?page=1"
  // Snip ...
}

The API follows the REST principle that a network client can interact with an application entirely through the hypermedia dynamically served by the server. The API follows this by providing links properties (self, next and prev) on all responses, indicating a set of available "affordances" or "related entities" available to the current response.

Links properties must be in the form of full URIs. This makes navigating the API easy from both a debugging perspective and from within flyway itself. This also facilitates the ability to use a full URI including querystring parameters to iterate through the API when kicking off a migration.

The self property should exist on every top level API response. Both next and prev only need to implemented on pages where pagination is required, such as the endpoint to iterate through all articles.

Pagination

Pagination is based on Copilot API pagination. The root level of a paginated API payload contains the following keys that relate to the result set:

Field Type Required Description Restrictions
page number Yes Page counter for paginated results (1 or 0 based) -
totalCount number Yes The total number of entities (not just on the current page) See below
brand string Yes The brand code of the content being migrated See Brand Validation below
prev link No The API URL that leads to the previous page (if this is not the first) -
self link Yes The API URL that leads to the current page -
next link No The API URL that leads to the next page (if this is not the last) Required if hasMore is true
hasMore boolean Yes Should be true if there are more pages -
data Array of stubs Yes The "page" of results providing identity and API links to the actual entities See below

If it is not possible to return an accurate totalCount either return the best estimate and refine it as requests get closer to the final page, or, if not known at all, return the count of all items up to the end of the current page and add one if hasMore is true.

Flyway will validate that the eventual totalCount matches the number of encountered entities.

Query parameters

Flyway will follow next to fetch further pages of results. Implementers may use their own query parameter scheme, but the demo API accepts the following parameters:

Data stubs

All entities in the data array must include the following fields:

Field Type Required Description
id string Yes the entity ID in the integration system
type string Yes the Flyway type (one of article, gallery, hotel, nativearticle, nativegallery, nativerecipe, product or recipe)
self link Yes a URL to retrieve the fully hydrated entity

Other fields from the full entity may be included. These will not be used by Flyway but can help with diagnostics and human readability.

Brand validation

All replies from the API should include a top level JSON property brand which can match any valid CNI brand code. For example vit for Vogue Italia. This is used to ensure that when you provide the flyway dashboard links to your integration API, it can only migrate expected content from your brand into your new Copilot instance. To start a migration you must select the brand you plan on migrating within the dashboard. Once the brand code from the API matches the brand code selected in the dashboard, migration of content can continue.

Alternative Language Translations

Note: This feature is only enabled for Vogue Paris.

Support is available for an enabled brand to migrate content which is available in the local language and in English published under distinct URIs. Each language variant should be migrated separately under a unique ID and must include the lang property (see language tags) indicating in which language it is written. The local language variant should include the alternateLang relationship containing a stub of the article/gallery in the alternative language (English - en-FR).

The all articles and all galleries endpoints should include links to both language variants of translated articles. Just including a reference in alternateLang does not guarantee full migration of the translation.

Resource Models

The Flyway Integration API response schema uses a number of resource types based on the Copilot content models. As a simplification for Flyway all content that relates to an article is fully hydrated in the get article API (and all content that relates to a gallery is fully hydrated in the get gallery API).

Resource IDs

The IDs used in the API should correspond to IDs used within the source CMS. The following rules apply.

Language Tags

The lang field used in most content models permits a restricted set of BCP 47 language tags. These are laid out in this Confluence page.

List of permitted language tags in the new format (as of 1st September 2021):

Markdown Text Fields

Where specified the Flyway Integration API can respond with fields in 2 flavors of markdown:

Relative URIs

const URI_REGEXP = /^[\p{Letter}0-9_#%]+(?:(?=([-/_][\p{Letter}0-9%#-]+))\1)*$/u;

In this API, as in the Copilot Content API, uri fields are relative paths from the root of the brand website (omitting the leading slash). They should match the regular expression URI_REGEXP. Although the pattern allows any letter, this is primarily intended to support Far Eastern characters. We recommend that markets using Latin characters, limit to lowercase a to z.

Leading and trailing slashes will be stripped if supplied.

The same pattern is used for Category slug, except that the slug should not include a slash (/). Some Verso Settings slugs require mixed case, but otherwise we advise against using uppercase if possible.

Inline Embeds

Sample body markdown with embedded image, gallery, article and product

[#image: /photos/5678]|||Image caption|||

[#gallery: /galleries/1234]|||Gallery caption|||

[#article: /articles/7654]

[#nativearticle: /nativearticles/4567]

[#product: /product/6789]

[#recipe: /recipes/1234]

Photos, galleries, articles, native articles/galleries, recipes and products may be embedded inline in an article, gallery or native article/gallery body. Any such content needs to be:

  1. Included in the inline array field of the article.
  2. Directly referenced in the body markdown as block embeds (see markdown example).

Photos are included in the inline array as fully hydrated Photo entities.

Within articles (or native articles), galleries (or native galleries) are also included in the inline array as fully hydrated Gallery entities (or Native Gallery). However within galleries (or native galleries), embedded galleries (and native galleries) should be provided in the form of an Embedded Gallery Stub (Embedded Native Gallery Stub) in the inlinefield and the fully hydrated gallery must be migrated separately.

Articles, native articles and recipes, also, need to be provided in the form of an Embedded Stub (or Embedded Native Article Stub) in the inline field and the fully hydrated article (or native article) must be migrated separately. (Note: the order in which you migrate the articles does not matter. The containing article and the embedded article may be included in the same batch migration, for example with a Get All Entities API endpoint).

Products are included in the inline array as fully hydrated Product entities.

When referencing entities in the body markdown, photos are included using the #image embed, galleries with #gallery, articles with #article, native galleries and articles with #nativegallery and #nativearticle respectively and products with #product.

As part of article migration by the Flyway service any hrefs referring to inline embedded content will be replaced with the hrefs of the migrated Copilot content. Any href matching the inlineHref of inline content will be replaced by the href of the corresponding Copilot entity. If omitted, the inlineHref will default to /photos/${id} for photos, /galleries/${id} for galleries, /articles/${id} for articles etc. If the hrefs in the body markdown use a different pattern to this then the inlineHref must be specified in the inline array. We advise against using a different prefix other than the Copilot collection name (e.g. use /articles/... for an article embed, /recipes/... for a recipe embed), otherwise you may get an obscure markdown validation error.

Draft articles and galleries

Draft articles and galleries can also be migrated as well as published and scheduled content. The only difference between the two is the presence of the publishHistory property. All published entities should have this object complete with pubDate and uri keys. An entity will be considered a draft if no publishHistory object is present.

When a gallery is embedded in article that is published, this embedded entity also needs to be published, and cannot be embedded as a draft.

Important notes on optional

valid example

{
  "title": "this is a title"
}
{
  "title": "this is a title",
  "subtitle": "this is a subtitle"
}

invalid example

{
  "title": "this is a title",
  "subtitle": null
}

When a value within this documentation is described as "optional", it means that the property should either be left out of the object completely, or be provided a valid value. null is still considered a value, and it is invalid for optional values. For optional array properties for which there is no value, the property may be omitted or an empty array [] supplied.

The examples use a schema that defines title as a required string and subtitle as an optional string. The top two objects are valid, while the bottom would be invalid.

Use of dataURIs

The use of data URI encoded images, fields or resources within the body property is invalid and will be rejected during schema validation. This restriction applies to articles, galleries and native articles.

Article

Sample article

{
  "type": "article",
  "id": "82da",
  "brand": "dmo",
  "lang": "de",
  "hed": "\"Blonde Ambition\": Universal bringt Madonna-Biopic ins Kino",
  "body": "\nMadonna ist eine lebende Legende. In den frühen 1980er-Jahren wurde sie zum Sinnbild für Auflehnung gegen das Establishment und der Emanzipation der Frau...\n",
  "dek": "Lang lag das Drehbuch in der Schublade, nun soll es endlich auf die große Leinwand kommen: das Madonna-Biopic \"Blonde Ambition\"\n",
  "seoTitle": "Madonna-Biopic \"Blonde Ambition\"",
  "seoDescription": "Lang lag das Drehbuch in der Schublade, nun soll es endlich auf die große Leinwand kommen: das Madonna-Biopic \"Blonde Ambition\". Mehr erfahren!",
  "tags": [
    "Filmtipps",
    "Star-News"
  ],
  "rubric": "Film ab!",
  "ledeCaption": "",
  "socialTitle": "Universal bringt Madonna-Biopic ins Kino",
  "socialDescription": "Film-Tipp zum Vormerken: das Madonna-Biopic \"Blonde Ambition\"\r\n",
  "contentSource": "digital_syndication",
  "canonicalUrl": "http://www.vogue.de/people-kultur/people-news/madonna-biopic-blonde-ambition-170425",
  "promoHed": "Universal bringt Madonna-Biopic ins Kino",
  "self": "https://flyway-api-demo.example.com/api/articles/82da",
  "contributorsAuthor": ["..."],
  "contributorsPhotographer": [],
  "inline": [],
  "photosLede": ["..."],
  "photosSocial": ["..."],
  "photosTout": ["..."],
  "categories": {
    "channels": ["..."],
    "tags": ["..."],
    "functional-tags": ["..."]
  },
  "publishHistory": {
    "pubDate": "2017-11-24T10:44:48.147Z",
    "uri": "people-kultur/people-news/madonna-biopic-blonde-ambition-170425"
  }
}

A top-level content type. Other content types are nested within this object.

Field Type Required Description Restrictions
type string Yes Content model name Must be article
id string Yes Source CMS ID See Resource IDs above
brand string Yes Short hand CNI brand code -
lang language tag Yes The language in which the content is written See language tags
hed string Yes The article headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
body string Yes The article body Copilot flavoured markdown
dek string Yes The article subhead Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists. Empty string is allowed
seoTitle string Yes The article seo title Plain text
seoCategory string No (default "evergreen") The article seo category Must be evergreen or news
seoDescription string Yes The article seo description Plain text
tags array of string Yes The article tags Array of plain text strings (may be empty). Does not allow duplicates. This field should be restricted to private tags (beginning with _). Public tags (aka "topics") should migrate to categories.tags property.
contentSource string No (default "web") The article origin One of digital_syndication, web, magazine, vogue_international or external_agency
canonicalUrl string No The canonical URL of the article if sourced from elsewhere Must be a full URL containing http or https
rubric string Yes a 'kicker', A free text category line. Plain text. Empty string is allowed.
socialTitle string Yes The article social media title Plain text
socialDescription string Yes The article social media description Plain text
photosSocial array of Photo No The article social media photo Can contain 0 or 1 image objects
promoHed string Yes The title shown in teasers (e.g. on index pages) Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to this document -
contributorsAuthor array of Contributor Yes Byline details of author(s) -
contributorsPhotographer array of Contributor No Details of photographer(s) to be included in byline -
inline array of Photo, Gallery, Product or Embedded Article or Recipe Stub No Photos, products and galleries with embedded links in the body -
photosLede array of Photo Yes The main photo of the article Can contain 0 or 1 image objects, but must not be undefined
ledeCaption string No The caption of the lede image Copilot Limited markdown. Supports Bold, Italic and Strikethrough
videosLede array of CNEVideo No The main video of the article Contains 1 CNE video object. Can be empty.
photosTout array of Photo Yes The image shown in teasers (e.g. on index pages) Must contain a min of 1 and a max of 1 image
categories object with the following keys Yes Categories associated with this content Must include sections (on Compass brands) or channels (for all other brands). Other valid keys are listed below
categories.sections array containing a single (sub)section Category Yes (Compass brands) Where in the site nav the content lives Must contain only 1 category. Must include the top level parent section if specifying a subsection.
categories.channels array containing at least one (sub)channel Category Yes (other brands) Where in the site nav the content lives plus other associated (sub)channels Must contain at least one (sub)channel category. Must include the top level parent channel if specifying a subchannel.
categories.tags array of Category No (defaults empty) Public tags (aka "topics") under which this content is indexed Duplicates are not allowed.
categories.functional-tags array of Category No (defaults empty) Private tags for use by the platform associated with this content Duplicates are not allowed. Check to find out what functional tags are supported.
categories.contentWarnings array of Category No (defaults empty) Content warnings for this content Check that Content Warnings are supported before using this. A limited set of content warning categories are allowed. Duplicates are not allowed.
categories.verso-settings array of Category No (defaults empty) Categories to modify the layout of this content in Verso Duplicates are not allowed. The full parent hierarchy should be specified for each setting. Check with the Verso team to find out what settings are supported.
publishHistory object with keys listed below No Publication options for the article Draft articles should omit this property
publishHistory.pubDate string Yes Publication date ISO 8601 date format
publishHistory.uri string Yes Relative path to published article See Relative URIs for accepted pattern
publishHistory.recommendable boolean No (defaults true) If the article should appear in recommendations on other articles -
publishHistory.searchable boolean No (defaults true) If the article should appear on index pages -
alternateLang array containing a single Article stub No Translation of this article in another language Vogue Paris only. Can contain 0 or 1 article stubs. See alternative languages

Article Stub

Sample article stub

{
  "type": "article",
  "id": "82db",
  "brand": "vpa",
  "lang": "en-FR",
  "hed": "\"Blonde Ambition\": Universal brings Madonna biopic to the big screen",
  "self": "https://flyway-api-demo.example.com/api/articles/82db"
}

A minimal article stub used to specify translations in the alternateLang relationship property. See alternative languages.

Field Type Required Description Restrictions
type string Yes Content model name Must be article
id string Yes Source CMS ID See Resource IDs above
brand string Yes Short hand CNI brand code Only vpa (Vogue Paris) is allowed
lang language tag Yes The language in which the article is written Only en-FR (English) is allowed
hed string Yes The article headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to the full document -

Embedded Stub (Article or Recipe)

Sample embedded article stub

{
  "type": "article",
  "id": "82db",
  "brand": "dmo",
  "lang": "en-GB",
  "hed": "\"Blonde Ambition\": Universal brings Madonna biopic to the big screen",
  "self": "https://flyway-api-demo.example.com/api/articles/82db",
  "publishHistory": {
    "pubDate": "2017-11-24T10:44:48.147Z",
    "uri": "people-kultur/people-news/madonna-biopic-blonde-ambition-170425"
  }
}

A minimal stub used to specify inline article and recipe embeds in the inline property. See inline embeds.

Field Type Required Description Restrictions
type string Yes Content model name Must be article or recipe
id string Yes Source CMS ID See Resource IDs above
inlineHref string No (default /articles/${id}) Href used for article body embed See Inline Embeds
brand string Yes Short hand brand code Should be same as brand on enclosing article or gallery
lang language tag Yes The language in which the article is written Should be same as the enclosing article or gallery
hed string Yes The article headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to the full document -
publishHistory object with keys listed below Yes Publication options for the article -
publishHistory.pubDate string Yes Publication date ISO 8601 date format
publishHistory.uri string Yes Relative path to published article See Relative URIs for accepted pattern
publishHistory.recommendable boolean No (defaults true) If the article should appear in recommendations on other articles -
publishHistory.searchable boolean No (defaults true) If the article should appear on index pages -

Native Article

Sample native article

{
  "type": "nativearticle",
  "id": "0a14",
  "brand": "dmo",
  "lang": "en-GB",
  "hed": "Native article example",
  "body": "**Native article body copy supports exactly the same styles and embeds as the regular Article model.**\n\nVeggies es bonus vobis, proinde vos postulo essum magis kohlrabi welsh onion daikon amaranth tatsoi tomatillo melon azuki bean garlic.\n\nGumbo beet greens corn soko endive gumbo gourd. _Parsley_ shallot courgette tatsoi pea sprouts fava bean collard greens dandelion okra wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.\n\n## Heading 2\n\nTurnip greens yarrow ~~ricebean~~ rutabaga endive [cauliflower](http://www.foo.com) sea lettuce kohlrabi amaranth water spinach avocado daikon napa cabbage asparagus winter purslane kale. Celery potato scallion desert raisin horseradish spinach carrot soko. Lotus root water spinach fennel kombu maize bamboo shoot green bean swiss chard seakale pumpkin onion chickpea gram corn pea. Brussels sprout coriander water chestnut gourd swiss chard wakame kohlrabi beetroot carrot watercress. \n\n### Heading 3\n\nCorn amaranth salsify bunya nuts nori azuki bean chickweed potato bell pepper artichoke.\n\n[#image: /photos/710f]|||Image caption|||\n\nNori grape silver beet broccoli kombu beet greens fava bean potato quandong celery. Bunya nuts black-eyed pea prairie turnip leek lentil turnip greens parsnip. Sea lettuce lettuce water chestnut eggplant winter purslane fennel azuki bean earthnut pea sierra leone bologi leek soko chicory celtuce parsley jícama salsify.\n\n[#video: https://www.youtube.com/embed/ZCTBHm29SrM]\n\nCelery quandong swiss chard chicory earthnut pea potato. Salsify taro catsear garlic gram celery bitterleaf wattle seed collard greens nori. Grape wattle seed kombu beetroot horseradish carrot squash brussels sprout chard.\n\n#### Heading 4\n\n> Celery quandong swiss chard chicory earthnut pea potato. Salsify taro catsear garlic gram celery bitterleaf wattle seed collard greens nori. \n\nGrape wattle seed kombu beetroot horseradish carrot squash brussels sprout chard.",
  "dek": "This is an example of a native article for the Migrations team",
  "bylineOption": "produced",
  "campaignUrl": "http://www.foo.com",
  "seoCategory": "evergreen",
  "seoTitle": "SEO title example",
  "seoDescription": "SEO description example",
  "tags": [
    "migration",
    "article",
    "team"
  ],
  "contentSource": "vogue_international",
  "rubric": "Example kicker",
  "ledeCaption": "Here's the story [image](http://foo.com)",
  "canonicalUrl": "",
  "socialTitle": "Here's the test social title",
  "socialDescription": "Here's the test social description",
  "promoHed": "Here's the promo title",
  "self": "https://flyway-api-demo.example.com/api/nativearticles/0a14",
  "inline": ["..."],
  "advertiser": [
    {
      "type": "advertiser",
      "id": "1151",
      "name": "Prada",
      "url": "http://prada.com",
      "photosLogo": [
        {
          "type": "photo",
          "id": "c1df",
          "filename": "ipad_logo_nero.png",
          "url": "http://www.prada.com/etc/designs/prada/images/base/ipad_logo_nero.png",
          "title": "ipad_logo_nero.png",
          "cropMode": "TOP",
          "credit": "Prada"
        }
      ]
    }
  ],
  "photosLede": ["..."],
  "photosSocial": ["..."],
  "photosTout": ["..."],
  "contributorsAuthor": ["..."],
  "categories": {
    "sections": ["..."],
    "tags": ["..."]
  },
  "publishHistory": {
    "pubDate": "2018-02-22T12:34:53.459Z",
    "uri": "beauty/anzeige/native-article-example"
  }
}

A top-level content type for sponsored content. Other content types are nested within this object. Native article refers to a sponsored or paid for article and should contain a link to the associated advertiser.

Field Type Required Description Restrictions / Notes
type string Yes Content model name Must be nativearticle
id string Yes Source CMS ID See Resource IDs above
brand string Yes Short hand CNI brand code -
lang language tag Yes The language in which the content is written See language tags
hed string Yes The article headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
body string Yes The article body Copilot flavoured markdown
dek string Yes The article subhead Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists. Empty string is allowed
bylineOption string No (default "produced") The advertiser byline wording option See native byline options.
bylineVariant string No (see Notes) The advertiser byline variation (whether to show logo) Either logo (default if advertiser has logo) or text (default if advertiser has no logo)
campaignUrl string Yes The sponsored campaign url URL
advertiser Advertiser Yes The advertiser to link this article to -
seoTitle string Yes The article seo title Plain text
seoCategory string No (default "evergreen") The article seo category Must be evergreen or news
seoDescription string Yes The article seo description Plain text
tags array of string Yes The article tags Array of plain text strings (may be empty). Does not allow duplicates. This field should be restricted to private tags (beginning with _). Public tags (aka "topics") should migrate to categories.tags property.
contentSource string No (default "web") The article origin Must be Digital Syndication, Web, Magazine, Vogue International or External Agency
canonicalUrl string No The canonical URL of the article if sourced from elsewhere Must be a full URL containing http or https
rubric string Yes a 'kicker', A free text category line. Plain text. Empty string is allowed.
socialTitle string Yes The article social media title Plain text
socialDescription string Yes The article social media description Plain text
photosSocial array of Photo No The article social media photo Can contain 0 or 1 image objects
promoHed string Yes The title shown in teasers (e.g. on index pages) Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to this document -
contributorsAuthor array of Contributor Yes Byline details -
inline array of Photo, Gallery or Embedded Article Stub No Photos and galleries with embedded links in the body -
photosLede array of Photo Yes The main photo of the article Can contain 0 or 1 image objects, but must not be undefined
ledeCaption string No The caption of the lede image Copilot Limited markdown. Supports Bold, Italic and Strikethrough
photosTout array of Photo Yes The image shown in teasers (e.g. on index pages) Must contain a min of 1 and a max of 1 image
categories object with the following keys Yes Categories associated with this content Must include sections (on Compass brands) or channels (for all other brands). Other valid keys are listed below
categories.sections array containing a single (sub)section Category Yes (Compass brands) Where in the site nav the content lives Must contain only 1 category. Must include the top level parent section if specifying a subsection.
categories.channels array containing at least one (sub)channel Category Yes (other brands) Where in the site nav the content lives plus other associated (sub)channels Must contain at least one (sub)channel category. Must include the top level parent channel if specifying a subchannel.
categories.tags array of Category No (defaults empty) Public tags (aka "topics") under which this content is indexed Duplicates are not allowed.
categories.functional-tags array of Category No (defaults empty) Private tags for use by the platform associated with this content Duplicates are not allowed. Check to find out what functional tags are supported.
categories.contentWarnings array of Category No (defaults empty) Content warnings for this content Check that Content Warnings are supported before using this. A limited set of content warning categories are allowed. Duplicates are not allowed.
categories.verso-settings array of Category No (defaults empty) Categories to modify the layout of this content in Verso Duplicates are not allowed. The full parent hierarchy should be specified for each setting. Check with the Verso team to find out what settings are supported.
publishHistory object with keys listed below No Publication options for the article Draft articles should omit this property
publishHistory.pubDate string Yes Publication date ISO 8601 date format
publishHistory.uri string Yes Relative path to published article See Relative URIs for accepted pattern
publishHistory.recommendable boolean No (defaults true) If the article should appear in recommendations on other articles -
publishHistory.searchable boolean No (defaults true) If the article should appear on index pages -
alternateLang array containing a single Native article stub No Translation of this native article in another language Vogue Paris only. Can contain 0 or 1 native article stubs. See alternative languages

Native byline options

Default English mappings for bylineOption in Verso

const BYLINE_TEMPLATES = {
  brand_x_advertiser: t`${'brand'} X`,
  branded_content: t`Branded Content By`,
  created: t`Created By ${'brand'} For`,
  paid_post: t`Paid Post`,
  produced_by_advertiser: t`Produced By`,
  produced_by_brand: t`Produced By ${'brand'} With`,
  sponsored_content: t`Sponsored Content By`,
  produced: t`Produced by`,
  sponsored: t`Sponsored content`
}

The bylineOption field on native article and native gallery should be one of brand_x_advertiser, branded_content, created, paid_post, produced, produced_by_advertiser, produced_by_brand, sponsored or sponsored_content. It defaults to produced if omitted. Verso uses it to determine the wording to display in the sponsored content header unless it is overridden in the tenant config.

Native Article Stub

Sample native article stub

{
  "type": "nativearticle",
  "id": "0a15",
  "brand": "vpa",
  "lang": "en-FR",
  "hed": "Example of a native article",
  "self": "https://flyway-api-demo.example.com/api/nativearticles/0a15"
}

A minimal native article stub used to specify translations in the alternateLang relationship property. See alternative languages.

Field Type Required Description Restrictions
type string Yes Content model name Must be nativearticle
id string Yes Source CMS ID See Resource IDs above
brand string Yes Short hand CNI brand code Only vpa (Vogue Paris) is allowed
lang language tag Yes The language in which the article is written Only en-FR (English) is allowed
hed string Yes The article headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to the full document -

Embedded Native Article Stub

Sample embedded native article stub

{
  "type": "nativearticle",
  "id": "0a14",
  "brand": "dmo",
  "lang": "en-GB",
  "hed": "Native article example",
  "self": "https://flyway-api-demo.example.com/api/nativearticles/0a14",
  "publishHistory": {
    "pubDate": "2018-02-22T12:34:53.459Z",
    "uri": "beauty/anzeige/native-article-example"
  }
}

A minimal native article stub used to specify inline #nativearticle embeds in the inline property. See inline embeds.

Field Type Required Description Restrictions
type string Yes Content model name Must be nativearticle
id string Yes Source CMS ID See Resource IDs above
inlineHref string No (default /nativearticles/${id}) Href used for native article body embed See Inline Embeds
brand string Yes Short hand brand code Should be same as brand on enclosing article or gallery
lang language tag Yes The language in which the content is written Should be same as brand on enclosing article or gallery
hed string Yes The article headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to the full document -
publishHistory object with keys listed below Yes Publication options for the article -
publishHistory.pubDate string Yes Publication date ISO 8601 date format
publishHistory.uri string Yes Relative path to published article See Relative URIs for accepted pattern
publishHistory.recommendable boolean No (defaults true) If the article should appear in recommendations on other articles -
publishHistory.searchable boolean No (defaults true) If the article should appear on index pages -

Sample gallery

{
  "type": "gallery",
  "id": "gallery:1234",
  "brand": "dmo",
  "lang": "de-DE",
  "hed": "A party with food",
  "dek": "Lang lag das Drehbuch in der Schublade, nun soll es endlich auf die große Leinwand kommen: das Madonna-Biopic \"Blonde Ambition\"\n",
  "body": "Madonna ist eine lebende Legende. In den frühen 1980er-Jahren wurde sie zum Sinnbild für Auflehnung gegen das Establishment und der Emanzipation der Frau.",
  "seoTitle": "Madonna-Biopic \"Blonde Ambition\"",
  "seoDescription": "Lang lag das Drehbuch in der Schublade, nun soll es endlich auf die große Leinwand kommen: das Madonna-Biopic \"Blonde Ambition\". Mehr erfahren!",
  "tags": [],
  "rubric": "Film ab!",
  "photosSocial": ["..."],
  "socialTitle": "Universal bringt Madonna-Biopic ins Kino",
  "socialDescription": "Film-Tipp zum Vormerken: das Madonna-Biopic \"Blonde Ambition\"\r\n",
  "contentSource": "digital_syndication",
  "canonicalUrl": "http://www.vogue.de/people-kultur/people-news/madonna-biopic-blonde-ambition-170425",
  "promoHed": "Universal bringt Madonna-Biopic ins Kino",
  "photosLede": ["..."],
  "photosTout": ["..."],
  "contributorsAuthor": ["..."],
  "contributorsPhotographer": ["..."],
  "categories": {
    "sections": ["..."],
    "tags": ["..."],
    "contentWarnings": ["..."]
  },
  "inline": [],
  "items": [
    {
      "caption": "This food was really horrible within the context of this gallery!",
      "photo": {
        "type": "photo",
        "id": "586d",
        "altText": "some alt text",
        "caption": "the global caption for this photo that this gallery overrides",
        "title": "some-food.jpg",
        "tags": [],
        "filename": "some-food.jpg",
        "url": "https://flyway-api-demo.example.com/public/images/586d_some-food.jpg",
        "credit": "Pinterest"
      }
    },
    {
      "caption": "This food was really delicious within the context of this gallery!",
      "photo": {
        "type": "photo",
        "id": "544a",
        "altText": "some more alt text",
        "caption": "another global caption for this photo that this gallery overrides",
        "title": "some-more-food.jpg",
        "tags": [],
        "filename": "some-more-food.jpg",
        "url": "https://flyway-api-demo.example.com/public/images/544a_some-more-food.jpg",
        "credit": "Pinterest"
      }
    },
    {
      "caption": "",
      "product": {
        "id": "zgDOvJkk8dcf",
        "type": "product",
        "name": "Nokia 5.4",
        "description": "",
        "productType": "Phones",
        "composition": [],
        "offers": [
          {
            "seller": {
              "name": "Amazon"
            },
            "purchaseUri": "https://www.amazon.com/Nokia-Smartphone-Qualcomm-Snapdragon-Upgrades/dp/B08STXNT4K",
            "offerType": "purchase",
            "price": 250,
            "currency": "USD"
          },
          {
            ...
          }
        ],
        "photosTout": [
          {
            "type": "photo",
            "id": "544ab",
            "altText": "some more alt text",
            "title": "nokia_phone.jpg",
            "tags": [],
            "filename": "nokia_phone.jpg",
            "url": "https://flyway-api-demo.example.com/public/images/544ab_nokia_phone.jpg",
            "credit": "Pinterest"
          }
        ],
        "publishHistory": {
          "pubDate": "2021-04-07T15:22:43.890Z",
          "searchable": true,
          "uri": "product/606dcdc541bf976945513473"
        }
      }
    }
  ],
  "publishHistory": {
    "pubDate": "2017-11-24T10:44:48.147Z",
    "uri": "people-kultur/people-news/madonna-biopic-blonde-ambition-170425"
  }
}

A top-level or embedded content type to display collections of photos, and/or products. Other content types are nested within this object.

Can be used within inline article content.

Field Type Required Description Restrictions
type string Yes Content model name Must be gallery
id string Yes Source CMS ID See Resource IDs above
inlineHref string No (default /galleries/${id}) Href used for article body gallery embed Only used if the gallery is supplied in an article inline field. See Inline Embeds
brand string Yes Short hand CNI brand code -
lang language tag Yes The language in which the content is written See language tags
hed string Yes The gallery headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
dek string Yes The gallery subhead Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists. Empty string is allowed
body string No The optional gallery body Copilot flavoured markdown. May include Inline Embeds in which case inline should also be supplied
seoTitle string Yes The gallery seo title Plain text
seoCategory string No (default "evergreen") The gallery seo category Must be evergreen or news
seoDescription string Yes The gallery seo description Plain text
tags array of string Yes The tags of the gallery Array of plain text strings (may be empty). Does not allow duplicates. This field should be restricted to private tags (beginning with _). Public tags (aka "topics") should migrate to categories.tags property.
contentSource string No (default "web") The gallery origin One of digital_syndication, web, magazine, vogue_international or external_agency
canonicalUrl string No The canonical URL of the gallery if sourced from elsewhere Must be a full URL containing http or https
rubric string Yes a 'kicker', A free text category line. Plain text. Empty string is allowed.
socialTitle string Yes The gallery social media title Plain text
socialDescription string Yes The gallery social media description Plain text
photosLede array of Photo No An optional cover photo for the gallery Can contain 0 or 1 photo
ledeCaption string No Caption of the lede (cover) image Copilot Limited markdown. Supports Bold, Italic and Strikethrough
photosSocial array of Photo No The article social media photo Can contain 0 or 1 image objects
photosTout array of Photo Yes The image shown in teasers (e.g. on index pages) Must contain a min of 1 and a max of 1 image
promoHed string Yes The title shown in teasers (e.g. on index pages) Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to this document -
contributorsAuthor array of Contributor Yes Byline details of author(s) -
contributorsPhotographer array of Contributor No Details of photographer(s) to be included in byline -
categories object with the following keys Yes Categories associated with this content Must include sections (on Compass brands) or channels (for all other brands). Other valid keys are listed below
categories.sections array containing a single (sub)section Category Yes (Compass brands only) Where in the site nav the content lives Must contain only 1 category. Must include the top level parent section if specifying a subsection.
categories.channels array containing at least one (sub)channel Category Yes (other brands) Where in the site nav the content lives plus other associated (sub)channels Must contain at least one (sub)channel category. Must include the top level parent channel if specifying a subchannel.
categories.tags array of Category No (defaults empty) Public tags (aka "topics") under which this content is indexed Duplicates are not allowed.
categories.functional-tags array of Category No (defaults empty) Private tags for use by the platform associated with this content Duplicates are not allowed. Check to find out what functional tags are supported.
categories.contentWarnings array of Category No (defaults empty) Content warnings for this content Check that Content Warnings are supported before using this. A limited set of content warning categories are allowed. Duplicates are not allowed.
categories.verso-settings array of Category No (defaults empty) Categories to modify the layout of this content in Verso Duplicates are not allowed. The full parent hierarchy should be specified for each setting. Check with the Verso team to find out what settings are supported.
publishHistory object with keys listed below No Publication options for the gallery Draft galleries should omit this property. Galleries embedded in articles require it.
publishHistory.pubDate string Yes Publication date ISO 8601 date format
publishHistory.uri string Yes Relative path to published gallery See Relative URIs for accepted pattern
publishHistory.recommendable boolean No (defaults true) If the gallery should appear in recommendations on other galleries -
publishHistory.searchable boolean No (defaults true) If the gallery should appear on index pages -
alternateLang array containing a single Gallery stub No Translation of this gallery in another language Vogue Paris only. Can contain 0 or 1 gallery stubs. See alternative languages
inline array of Photo, Embedded Gallery Stub or Embedded Article Stub No Photos, articles or galleries with embedded links in the body Only required if a body is supplied and Inline Embeds are used
items array of objects Yes References the photo or product with gallery slide overrides Must contain at least 1 object.
item.photo photo Yes, if the item references a photo The photo this item references -
item.product product Yes, if the item references a product The Product this item references -
item.caption string No Can be used to override the caption value in the photo Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists
item.body string No The gallery item's body Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists
item.altText string No Can be used to override the altText value in the photo Plain text
item.title string No Can be used to override the title value in the photo Plain text
item.credit string No Can be used to override the credit value in the photo Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link

Notes:

The item caption, altText, title and credit value exist to override the original photo values within the confines of a displayed gallery. For example an image that is used in two different galleries may use a different caption based on the context of the photo within the gallery. The example gallery object shown will display this gallery with the item.caption described in the object definitions, rather than the one contained within the item.photo.

Sample gallery stub

{
  "type": "gallery",
  "id": "82db",
  "brand": "vpa",
  "lang": "en-FR",
  "hed": "\"Blonde Ambition\": Universal brings Madonna biopic to the big screen",
  "self": "https://flyway-api-demo.example.com/api/galleries/82db"
}

A minimal gallery stub used to specify translations in the alternateLang relationship property. See alternative languages.

Field Type Required Description Restrictions
type string Yes Content model name Must be gallery
id string Yes Source CMS ID See Resource IDs above
brand string Yes Short hand CNI brand code Only vpa (Vogue Paris) is allowed
lang language tag Yes The language in which the gallery is written Only en-FR (English) is allowed
hed string Yes The gallery headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to the full document -

Sample embedded gallery stub

{
  "type": "gallery",
  "id": "6ab8",
  "brand": "wrduk",
  "lang": "en-GB",
  "hed": "Gallery: Stephen Knapp's beautiful light-based art",
  "self": "https://flyway-api-demo.example.com/wrduk/galleries/6ab8",
  "publishHistory": {
    "pubDate": "2017-01-20T16:00:00.000Z",
    "uri": "gallery/stephen-knapp-lights"
  }
}

A minimal gallery stub used to specify a published inline gallery embed in the inline property. See inline embeds. Note that this is only used for inline galleries within another gallery. Within an article, a fully hydrated Gallery should be supplied in the inline field.

Field Type Required Description Restrictions
type string Yes Content model name Must be gallery
id string Yes Source CMS ID See Resource IDs above
inlineHref string No (default /galleries/${id}) Href used for gallery body embed See Inline Embeds
brand string Yes Short hand brand code Should be same as brand on enclosing gallery
lang language tag Yes The language in which the gallery is written Should be same as enclosing gallery
hed string Yes The gallery headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to the full document -
publishHistory object with keys listed below Yes Publication options for the gallery -
publishHistory.pubDate string Yes Publication date ISO 8601 date format
publishHistory.uri string Yes Relative path to published article See Relative URIs for accepted pattern
publishHistory.recommendable boolean No (defaults true) If the article should appear in recommendations on other articles -
publishHistory.searchable boolean No (defaults true) If the article should appear on index pages -

Sample native gallery

{
  "type": "nativegallery",
  "id": "nativegallery:1234",
  "bylineOption": "produced",
  "campaignUrl": "http://www.foo.com",
  "brand": "dmo",
  "lang": "de-DE",
  "hed": "A party with food",
  "dek": "Lang lag das Drehbuch in der Schublade, nun soll es endlich auf die große Leinwand kommen: das Madonna-Biopic \"Blonde Ambition\"\n",
  "seoTitle": "Madonna-Biopic \"Blonde Ambition\"",
  "seoDescription": "Lang lag das Drehbuch in der Schublade, nun soll es endlich auf die große Leinwand kommen: das Madonna-Biopic \"Blonde Ambition\". Mehr erfahren!",
  "tags": [],
  "rubric": "Film ab!",
  "photosSocial": ["..."],
  "socialTitle": "Universal bringt Madonna-Biopic ins Kino",
  "socialDescription": "Film-Tipp zum Vormerken: das Madonna-Biopic \"Blonde Ambition\"\r\n",
  "contentSource": "digital_syndication",
  "canonicalUrl": "http://www.vogue.de/people-kultur/people-news/madonna-biopic-blonde-ambition-170425",
  "promoHed": "Universal bringt Madonna-Biopic ins Kino",
  "photosTout": ["..."],
  "contributorsAuthor": ["..."],
  "categories": {
    "channels": ["..."]
  },
  "items": [
    {
      "caption": "This food was really horrible within the context of this gallery!",
      "photo": {
        "type": "photo",
        "id": "586d",
        "altText": "some alt text",
        "caption": "the global caption for this photo that this gallery overrides",
        "title": "some-food.jpg",
        "tags": [],
        "filename": "some-food.jpg",
        "url": "https://flyway-api-demo.example.com/public/images/586d_some-food.jpg",
        "credit": "Pinterest"
      }
    },
    {
      "caption": "This food was really delicious within the context of this gallery!",
      "photo": {
        "type": "photo",
        "id": "544a",
        "altText": "some more alt text",
        "caption": "another global caption for this photo that this gallery overrides",
        "title": "some-more-food.jpg",
        "tags": [],
        "filename": "some-more-food.jpg",
        "url": "https://flyway-api-demo.example.com/public/images/544a_some-more-food.jpg",
        "credit": "Pinterest"
      }
    }
  ],
  "advertiser": [
    {
      "type": "advertiser",
      "id": "1151",
      "name": "Prada",
      "url": "http://prada.com",
      "photosLogo": [
        {
          "type": "photo",
          "id": "c1df",
          "filename": "ipad_logo_nero.png",
          "url": "http://www.prada.com/etc/designs/prada/images/base/ipad_logo_nero.png",
          "title": "ipad_logo_nero.png",
          "cropMode": "TOP",
          "credit": "Prada"
        }
      ]
    }
  ],
  "publishHistory": {
    "pubDate": "2017-11-24T10:44:48.147Z",
    "uri": "people-kultur/people-news/madonna-biopic-blonde-ambition-170425"
  }
}

A top-level type to display sponsored collections of photos. Other content types are nested within this object.

Cannot be used within inline article content.

Field Type Required Description Restrictions
type string Yes Content model name Must be gallery
id string Yes Source CMS ID See Resource IDs above
brand string Yes Short hand CNI brand code -
lang language tag Yes The language in which the content is written See language tags
hed string Yes The gallery headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
dek string Yes The gallery subhead Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists. Empty string is allowed
body string No The optional gallery body Copilot flavoured markdown. May include Inline Embeds in which case inline should also be supplied
seoTitle string Yes The gallery seo title Plain text
seoCategory string No (default "evergreen") The gallery seo category Must be evergreen or news
seoDescription string Yes The gallery seo description Plain text
bylineOption string No (default "produced") The advertiser byline wording option See native byline options
bylineVariant string No (see Notes) The advertiser byline variation (whether to show logo) Either logo (default if advertiser has logo) or text (default if advertiser has no logo)
campaignUrl string Yes The sponsored campaign url URL
advertiser Advertiser Yes The advertiser to link this article to -
tags array of string Yes The tags of the gallery Array of plain text strings (may be empty). Does not allow duplicates. This field should be restricted to private tags (beginning with _). Public tags (aka "topics") should migrate to categories.tags property.
contentSource string No (default "web") The gallery origin One of digital_syndication, web, magazine, vogue_international or external_agency
canonicalUrl string No The canonical URL of the gallery if sourced from elsewhere Must be a full URL containing http or https
rubric string Yes a 'kicker', A free text category line. Plain text. Empty string is allowed.
socialTitle string Yes The gallery social media title Plain text
socialDescription string Yes The gallery social media description Plain text
photosLede array of Photo No An optional cover photo for the gallery Can contain 0 or 1 photo
ledeCaption string No Caption of the lede (cover) image Copilot Limited markdown. Supports Bold, Italic and Strikethrough
photosSocial array of Photo No The article social media photo Can contain 0 or 1 image objects
photosTout array of Photo Yes The image shown in teasers (e.g. on index pages) Must contain a min of 1 and a max of 1 image
promoHed string Yes The title shown in teasers (e.g. on index pages) Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to this document -
contributorsAuthor array of Contributor Yes Byline details -
categories object with the following keys Yes Categories associated with this content Must include sections (on Compass brands) or channels (for all other brands). Other valid keys are listed below
categories.sections array containing a single (sub)section Category Yes (Compass brands only) Where in the site nav the content lives Must contain only 1 category. Must include the top level parent section if specifying a subsection.
categories.channels array containing at least one (sub)channel Category Yes (other brands) Where in the site nav the content lives plus other associated (sub)channels Must contain at least one (sub)channel category. Must include the top level parent channel if specifying a subchannel.
categories.tags array of Category No (defaults empty) Public tags (aka "topics") under which this content is indexed Duplicates are not allowed.
categories.functional-tags array of Category No (defaults empty) Private tags for use by the platform associated with this content Duplicates are not allowed. Check to find out what functional tags are supported.
categories.contentWarnings array of Category No (defaults empty) Content warnings for this content Check that Content Warnings are supported before using this. A limited set of content warning categories are allowed. Duplicates are not allowed.
categories.verso-settings array of Category No (defaults empty) Categories to modify the layout of this content in Verso Duplicates are not allowed. The full parent hierarchy should be specified for each setting. Check with the Verso team to find out what settings are supported.
publishHistory object with keys listed below No Publication options for the gallery Draft galleries should omit this property. Galleries embedded in articles require it.
publishHistory.pubDate string Yes Publication date ISO 8601 date format
publishHistory.uri string Yes Relative path to published gallery See Relative URIs for accepted pattern
publishHistory.recommendable boolean No (defaults true) If the gallery should appear in recommendations on other galleries -
publishHistory.searchable boolean No (defaults true) If the gallery should appear on index pages -
alternateLang array containing a single Gallery stub No Translation of this gallery in another language Vogue Paris only. Can contain 0 or 1 gallery stubs. See alternative languages
inline array of Photo, Embedded Gallery Stub or Embedded Article Stub No Photos, articles or galleries with embedded links in the body Only required if a body is supplied and Inline Embeds are used
items array of objects Yes References the photo with any required gallery local values Must contain at least 1 object.
item.photo photo Yes The photo this item references -
item.caption string No Can be used to override the caption value in the photo Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists
item.altText string No Can be used to override the altText value in the photo Plain text
item.title string No Can be used to override the title value in the photo Plain text
item.credit string No Can be used to override the credit value in the photo Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link

Notes:

The item caption, altText, title and credit value exist to override the original photo values within the confines of a displayed gallery. For example an image that is used in two different galleries may use a different caption based on the context of the photo within the gallery. The example gallery object shown will display this gallery with the item.caption described in the object definitions, rather than the one contained within the item.photo.

Sample embedded native gallery stub

{
  "type": "nativegallery",
  "id": "6ab8",
  "brand": "dmo",
  "lang": "en-GB",
  "hed": "Gorgeous photos of brand X",
  "self": "https://flyway-api-demo.example.com/dmo/nativegalleries/6ab8",
  "publishHistory": {
    "pubDate": "2017-01-20T16:00:00.000Z",
    "uri": "b/gallery/brand-x"
  }
}

A minimal native gallery stub used to specify a published inline #nativegallery embed in the inline property. See inline embeds. Note that this is only used for inline native galleries within another gallery or native gallery. Within an article, a fully hydrated Native Gallery should be supplied in the inline field.

Field Type Required Description Restrictions
type string Yes Content model name Must be nativegallery
id string Yes Source CMS ID See Resource IDs above
inlineHref string No (default /nativegalleries/${id}) Href used for gallery body embed See Inline Embeds
brand string Yes Short hand brand code Should be same as brand on enclosing gallery
lang language tag Yes The language in which the gallery is written Should be same as enclosing gallery
hed string Yes The gallery headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to the full document -
publishHistory object with keys listed below Yes Publication options for the gallery -
publishHistory.pubDate string Yes Publication date ISO 8601 date format
publishHistory.uri string Yes Relative path to published article See Relative URIs for accepted pattern
publishHistory.recommendable boolean No (defaults true) If the native gallery should appear in recommendations on other articles -
publishHistory.searchable boolean No (defaults true) If the native gallery should appear on index pages -

Contributor

Sample contributor

{
  "type": "contributor",
  "id": "2eb5",
  "name": "Vogue.de",
  "tags": [],
  "uri": "die-redaktion/voguede",
  "socialMedia": [
    { "network": "Twitter", "handle": "@johnsmith" }
  ]
}

Contributors are supplied in contributorsAuthor and contributorsPhotographer arrays of an article or gallery. These fields are used to populate the byline. The related content will usually be listed on the contributor page specified by the uri.

Field Type Required Description Restrictions
type string Yes Content model name Must be contributor
id string Yes Source CMS ID See Resource IDs above
name string Yes Name displayed on byline Plain Text
tags array of string Yes Search tags Array of plain text strings. May be an empty array, but not undefined. Does not allow duplicates.
uri string Yes Relative path to contributor page -
bio string No Contributor biography description Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists. Empty string is allowed
title string No Title (e.g. Editor in chief) Plain Text
socialMedia array of object No Social Media handles for contributors Array of objects containing keys network and handle.
photosTout array of Photo No A photo of the contributor Should only contain a max of 1 image

Notes

For socialMedia the accepted list of networks is one of: 'Facebook', 'Twitter', 'LinkedIn', 'Instagram', 'Google+', 'Pinterest', 'Tumblr', 'WordPress'. An example object might look like { network: 'Twitter', handle: '@johnsmith' }.

For the photosTout photo object, a contributor could upload a photo of themselves, making a circular reference for the attribution through the contributorsPhotographer attribute. An api implementing support for this will need to put guards in place to detect and exit this infinite lookup by omitting photosTout as long as the photo gets attributed to the contributor once.

Advertiser

Sample advertiser

{
  "type": "advertiser",
  "id": "54d1",
  "name": "L’Oréal Paris",
  "url": "https://loreal.com",
  "photosLogo": [
    {
      "type": "photo",
      "id": "c1df",
      "filename": "loreal_logo.svg.png",
      "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/L%27Or%C3%A9al_logo.svg/1600px-L%27Or%C3%A9al_logo.svg.png",
      "title": "loreal_logo.svg.png",
      "credit": "L’Oréal"
    }
  ]
}

Advertisers are used in advertiser of a native article or native gallery.

Field Type Required Description Restrictions
type string Yes Content model name Must be advertiser
id string Yes Source CMS ID See Resource IDs above
name string Yes Name displayed on byline Plain Text
url string Yes A full url that links to an advertiser Valid http(s) URL
photosLogo array of Photo Yes (may be empty) The brand logo of the advertiser Max one photo, if supplied

Photo

Sample photo

{
  "type": "photo",
  "id": "54b1",
  "inlineHref": "/photos/54b1",
  "altText": "Madonna",
  "caption": "",
  "credit": "Getty Images",
  "title": "Madonna Presents An Evening of Music, Art, Mischief and Performance to Benefit Raising Malawi",
  "notes": "Some internal notes on this image",
  "tags": [],
  "cropMode": "TOP",
  "filename": "madonna_2015_gettyimages-494171282__ethan_miller_quer.jpg",
  "url": "https://flyway-api-demo.example.com/public/images/54b0_madonna_2015_gettyimages-494171282__ethan_miller_quer.jpg",
  "categories": {
    "contentWarnings": ["..."]
  },
}

Photos are used in the photosTout, photosLede, inline of an article and the items of a gallery.

Field Type Required Description Restrictions
type string Yes Content model name Must be photo
id string Yes Source CMS ID See Resource IDs above
inlineHref string No (default /photos/${id}) Href used in article body for image embed See Inline Embeds
altText string No (default "") Image alt text Plain text
caption string No (default from EXIF data) Default image caption (maybe overridden). Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists. Set to an empty string "" to ignore exif data.
contributorsPhotographer array of Contributor No The photographers -
credit string Yes Image credit/copyright Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link
title string Yes Image title Plain text
tags array of string No Search tags Array of plain text strings. Does not allow duplicates.
filename string Yes Filename to use when uploading Valid image filename with extension
url string Yes Full URL of original image (including metadata) -
aspectRatios array of {x, y, width, height, aspectRatio} No Crops required of the image. Allowable values for aspectRatio must include one of the following values: '3:2', '2:3', '16:9', '4:3', '1:1'. Also min value for both x and y is 0 while min value for both height and width is 1.
restrictCropping boolean No (default: false) if the photo should never be cropped -
notes string No Internal notes Plain text
cropMode string No (uses Copilot default, usually TOP) Part of photo to crop when generating One of TOP_LEFT, TOP, TOP_RIGHT, LEFT, CENTER, RIGHT, BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT
categories object with keys contentWarnings Yes - -
categories.contentWarnings array of Category No, (defaults empty) Content warnings for this photo Sub-categories and duplicates are not allowed.

Notes:

url - The image url should include any authentication required to enable Flyway to download the original image and upload it to Copilot where any metadata will be processed and the required image sizes generated.

Crops and Aspect Ratios

The same photo may be rendered at different sizes and aspect ratios depending on where it is being used, the orientation (portrait, square or landscape) of the original and on what device it is viewed. In galleries the photo will always be displayed in its original aspect ratio. For teasers, story images and inline it may be cropped to another appropriate aspect ratio.

The aspect ratios (cropped as required) supported and used are '3:2', '2:3', '16:9', '4:3', '1:1'. By default when images are rendered in an aspect ratio other than the original they are cropped to the top centre (TOP) using as much of the original as possible. The cropMode defines the fixed point around which cropping happens. By default this is the top centre (TOP). If migrating photos that you know should be cropped to a different fixed point you can specify a different cropMode. You can see the results of cropping on the photo editor page in Copilot.

If in your source CMS you have manual crops in any of the above aspect ratios you can specify the coordinates of the custom crop. In aspectRatios you may supply an array with objects containing the relevant aspectRatio, the top left x, y coordinate of the crop, and the width and height of the crop. The crop coordinate and size should be based on the required region of the original upload. Only include the aspect ratios for which you have a manual crop. Other aspect ratios will be automatically generated. If you are not using manual crops we recommend that you omit aspectRatios.

If you are using photos for which you are contractually not permitted to crop, then such photos may be migrated with restrictCropping with a value of true. In such case you should omit aspectRatios and cropMode since these cannot apply. Please ensure that such photos aren't used as teaser images (photosTout). Setting this property for images used in teasers can break the layout of index pages and is not allowed.

Category

See Categories below for examples and details.

Field Type Required Description Restrictions
type string Yes Content model name Must be category
name string Yes The name of the category Plain text for display in Copilot and to the consumer unless for platform use only.
slug string Yes Unique slug for category section Part of relative uri for category page unless for platform use only. Allowed values may be defined for some category roots.
parent Category On subcategory only The parent category for a subcategory Parent category may not have a parent except verso-settings which has a deep hierarchy. Do not supply the root category as a parent.

Categories

Sample categories object for an AD Pro article (i.e. non-Compass brand).

{
  "channels": [
    {
      "type": "category",
      "name": "AD Pro",
      "slug": "ad-pro"
    },
    {
      "type": "category",
      "name": "Newsroom",
      "slug": "newsroom",
      "parent": {
        "type": "category",
        "name": "AD Pro",
        "slug": "ad-pro"
      }
    }
  ],
  "functional-tags": [
    {
      "type": "category",
      "name": "_syndication_noshow",
      "slug": "syndication-noshow"
    }
  ],
  "tags": [
    {
      "type": "category",
      "name": "ad pro",
      "slug": "ad-pro"
    },
    {
      "type": "category",
      "name": "News",
      "slug": "news"
    }
  ],
  "verso-settings": [
    {
      "type": "category",
      "name": "Text Above Center Grid Width",
      "slug": "TextAboveCenterGridWidth",
      "parent": {
        "type": "category",
        "name": "Variation",
        "slug": "variation",
        "parent": {
          "type": "category",
          "name": "Content Header",
          "slug": "ContentHeader",
          "parent": {
            "type": "category",
            "name": "Article Settings",
            "slug": "article-settings"
          }
        }
      }
    },
    {
      "type": "category",
      "name": "One Column (no ad rail)",
      "slug": "OneColumn",
      "parent": {
        "type": "category",
        "name": "variation",
        "slug": "variation",
        "parent": {
          "type": "category",
          "name": "Body Layout",
          "slug": "ChunkedArticleContent",
          "parent": {
            "type": "category",
            "name": "Article Settings",
            "slug": "article-settings"
          }
        }
      }
    }
  ]
}

Sample categories object for a Compass brand article.

{
  "sections": [
    {
      "type": "category",
      "slug": "people-news",
      "name": "People-News",
      "parent": {
        "type": "category",
        "slug": "lifestyle",
        "name": "Lifestyle"
      }
    }
  ],
  "tags": [
    {
      "type": "category",
      "slug": "news",
      "name": "News"
    },
    {
      "type": "category",
      "slug": "minor-celebrity",
      "name": "Minor Celebrity"
    }
  ],
  "contentWarnings": [
    {
      "type": "category",
      "slug": "alcohol_content",
      "name": "Alcohol content"
    },
    {
      "type": "category",
      "slug": "drug_content",
      "name": "Drug content"
    }
  ]
}

A category is a way to categorize content in Copilot against a known structure. For example, it is used to describe in which channel, sub-channel or section of the brand site an article or gallery can be found. It can be used for grouping related content under a tag on our consumer facing website. Or it can be used internally by our tools, for example to indicate articles that should not be exposed as an AMP page.

All primary content must be associated with at least one channel or section. Compass brands (Vogue and GQ outside the US) currently use sections. Other brands migrating direct to Verso should use channels. You should specify one or the other but not both. The primary slug values determine the ad unit path. So in the Compass example that would be lifestyle/people-news, and in the AD Pro example it would be ad-pro/newsroom.

The sections array should contain only one category. If specifying a sub-section, the top level parent section category should also be supplied. In the Compass brand example, an article with this category would be found under "People-News" (/lifestyle/people-news) but would also be listed on the "Lifestyle" page (/lifestyle).

The channels array may contain multiple categories, which may correspond to top level channels or sub-channels. The content may be included in the river and feeds for any specified channel or sub-channel. Sub-channel categories must specify the parent channel category (otherwise they will be assumed to be top level channels). The first (sub)channel supplied determines where in the channel nav the content will be displayed.

One or more category tags can also be specified using the categories.tags array. Brands may use a flat non-hierarchical tagging system or organise their tags under parent categories, e.g. "Meghan Markle" (meghan-markle) under "Celebrity" (celebrity). Tags should not contain private tags which begin with an underscore. Content will appear on the relevant tag pages. For the Compass example the content will be listed on /tags/news and /tags/minor-celebrity pages.

Functional tags are used by the platform to affect how the content is handled or displayed. For example whether a piece of content should be excluded from the river, feeds or AMP pages. Check which functional tags are supported by your brand before specifying them.

A category can also be used to flag a specific type of content in Copilot. The contentWarnings array can contain multiple category tags with specific slugs referring to different types of warnings. In the Compass example, an article with these content warnings would inform the consumer that it's contents contain alcohol and drug content. Ensure that these are supported for your brand before using them.

Field Type Required Description Restrictions
categories object with the following keys Yes Categories associated with the content Must include sections (on Compass brands) or channels (for all other brands). Other valid keys are listed below
categories.sections array containing a single (sub)section Category Yes (Compass brands) Where in the site nav the content lives Must contain only 1 category. Must include the top level parent section if specifying a subsection.
categories.channels array containing at least one (sub)channel Category Yes (other brands) Where in the site nav the content lives plus other associated (sub)channels Must contain at least one (sub)channel category. Must include the top level parent channel if specifying a subchannel.
categories.tags array of Category No (defaults empty) Public tags (aka "topics") under which the content is indexed Duplicates are not allowed.
categories.functional-tags array of Category No (defaults empty) Private tags for use by the platform associated with the content Duplicates are not allowed. Check to find out what functional tags are supported.
categories.contentWarnings array of Category No (defaults empty) Content warnings for the content Check that Content Warnings are supported before using this. A limited set of content warning categories are allowed. Duplicates are not allowed.
categories.contentWarnings.slug string Yes Unique content warning slug One of sexual_content, alcohol_content, drug_content or death_content
categories.verso-settings array of Category No (defaults empty) Categories to modify the layout of the content in Verso Duplicates are not allowed. The full parent hierarchy should be specified for each setting. Check with the Verso team to find out what settings are supported.

Product

Sample product

{
  "type": "product",
  "id": "zgDOvJkk8dcf",
  "lang": "en-US",
  "name": "Nokia 5.4",
  "description": "Sample description of the Nokia 5.4 phone",
  "productType": "Phones",
  "composition": ["metal", "plastic"],
  "offers": [
    {
      "seller": {
        "name": "Amazon"
      },
      "purchaseUri": "https://www.amazon.com/Nokia-Smartphone-Qualcomm-Snapdragon-Upgrades/dp/B08STXNT4K",
      "offerType": "purchase",
      "price": 250,
      "currency": "USD"
    },
    {
      ...offer
    }
  ],
  "photosTout": [
    {
      [photo]
    }
  ],
  "media": [photo, photo, photo],
  "publishHistory": {
    "pubDate": "2021-04-07T15:22:43.890Z",
    "searchable": true,
    "uri": "product/606dcdc541bf976945513473"
  }
}

Products can be used as a top level content type, in the items of a gallery or within inline article content.

Field Type Required Description Restrictions
type string Yes Content model name Must be product
id string Yes Source CMS ID See Resource IDs above
brand string Cf Restrictions Short hand CNI brand code Required for top level content. Optional for products included in gallery or articles.
lang language tag Yes The language in which the product is written See language tag
self Links Cf Restrictions Contains a link to this document Required for top level content. Optional for products included in gallery or articles.
name string Yes Name of the product -
description string No Description text -
productType string No Type of product e.g: phone, makeup cream, earbuds If included, permitted values must be agreed and configured in Copilot
composition array of strings No Element that make up the product, can be an ingredients list If used, Copilot must be configured to display this field
offers array of Offer Yes - Should contain at least 1 offer
photosTout array of Photo Yes The primary product image Must contain exactly 1 image
media array of Photo No Alternative product images Images must be unique
categories object with keys channels No - -
categories.channels array of Category No Must contain at least one (sub)channel category if supplied
publishHistory object with keys listed below Cf Restrictions Publication options for the product Required for products included in gallery or articles. Optional for top level content.
publishHistory.pubDate string Cf Restrictions Publication date ISO 8601 date format
publishHistory.uri string Cf Restrictions Relative path to published product We recommend using product/{id} as page will not be shown on Verso

Offer

Sample offer

{
  "seller": {
    "name": "Amazon"
  },
  "purchaseUri": "https://www.amazon.com/Nokia-Smartphone-Qualcomm-Snapdragon-Upgrades/dp/B08STXNT4K",
  "offerType": "purchase",
  "price": 250,
  "currency": "USD"
}

Offers are used in the offers of a product.

Field Type Required Description Restrictions
seller object with keys name Yes Vendor details -
seller.name string Yes Name of the seller -
purchaseUri string Yes Link to the offer Must be a valid URI (http, https)
offerType string Yes Type of offer Allowed values: 'trial', 'purchase'
price number Yes price of the offer Maximum of 2 decimal places allowed, cannot be negative
comparisonPrice number No original price to compare against Maximum of 2 decimal places allowed, cannot be negative
currency string Yes ISO 4217 currency code for the price and comparisonPrice Allowed values: 'EUR','GBP','INR','JPY','MXN','RUB','TWD','USD'

CNEVideo

Sample CNE video

{
  "type": "cnevideo",
  "id": "zgDOvJkk8dcf",
  "cneId": "5f3ddcd042b5f06e18c1353b
}

Videos which can be embedded in the videosLede of an article.

Field Type Required Description Restrictions
type string Yes Content model name Must be cnevideo
id string Yes Source CMS ID See Resource IDs above
cneId string Yes ID of the already migrated CNE Video Must be 24 hexadecimal characters

Recipe

Sample recipe

  {
    "type": "recipe",
    "id": "recipe-id-1",
    "brand": "hg",
    "lang": "en-GB",
    "self": "/recipes/recipe-id-1",
    "body": "Lamb, lemon, cilantro, arugula—in our house, these ingredients scream summer, so it seemed natural to combine them, along with a few other ingredients, to make a burger with a bright, citrusy yogurt sauce. The arugula does double duty as a topping and a side salad, keeping this meal quick, easy, and light. My partner and I found this burger doesn’t need cheese, but if you feel compelled to add it, it pairs particularly well with nutty, earthy cheeses like sheep’s-milk Gouda, aged cow’s milk Gouda, and Manchego, though you will only need half as much yogurt sauce. *—Jarrett Melendez*",
    "canonicalUrl": "",
    "contentSource": "web",
    "dek": "Some recipe dek",
    "hed": "Some recipe hed",
    "issueDate": "",
    "promoDek": "This flavorful lamb patty with lemony yogurt sauce is guaranteed to spice up your burger routine. ",
    "promoHed": "Lamb Burgers With Yogurt Sauce and Arugula",
    "seoDescription": "This flavorful lamb patty with lemony yogurt sauce is guaranteed to spice up your burger routine. ",
    "seoTitle": "Lamb Burgers With Yogurt Sauce and Arugula",
    "socialDescription": "This flavorful lamb patty with lemony yogurt sauce is guaranteed to spice up your burger routine. ",
    "socialTitle": "Lamb Burgers With Yogurt Sauce and Arugula",
    "tags": [],
    "temperatures": {
      "displayTemp": "",
      "preheatTemp": null,
      "cookingTemp": null
    },
    "times": {
      "displayTime": "",
      "prepTime": "",
      "activeTime": "",
      "totalTime": ""
    },
    "servingSizeInfo": {
      "servingSizeDescription": "4 servings",
      "servingSizeUnit": "",
      "servingSizeRangeFrom": null,
      "servingSizeRangeTo": null
    },
    "prepNotes": "",
    "prepNotesHed": "",
    "byline": "",
    "source": "",
    "amgUserId": "",
    "isPublic": true,
    "restaurant": "",
    "issueMonth": "July",
    "issueYear": 2021,
    "ingredientGroups": [
      {
        "hed": "",
        "ingredients": [
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "1¼ lb. ground lamb",
            "treatment": "",
            "note": "",
            "description": "1¼ lb. ground lamb"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "1 lemon",
            "treatment": "",
            "note": "",
            "description": "1 lemon"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "2 garlic cloves",
            "treatment": "",
            "note": "",
            "description": "2 garlic cloves"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "1 tsp. ground coriander",
            "treatment": "",
            "note": "",
            "description": "1 tsp. ground coriander"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "1½ tsp. Diamond Crystal or 1 tsp. Morton kosher salt, divided",
            "treatment": "",
            "note": "",
            "description": "1½ tsp. Diamond Crystal or 1 tsp. Morton kosher salt, divided"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "1 tsp. freshly ground black pepper, divided",
            "treatment": "",
            "note": "",
            "description": "1 tsp. freshly ground black pepper, divided"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "¼ cup (packed) cilantro leaves with tender stems",
            "treatment": "",
            "note": "",
            "description": "¼ cup (packed) cilantro leaves with tender stems"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "½ cup plain whole-milk Greek yogurt",
            "treatment": "",
            "note": "",
            "description": "½ cup plain whole-milk Greek yogurt"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "4 Tbsp. extra-virgin olive oil, divided",
            "treatment": "",
            "note": "",
            "description": "4 Tbsp. extra-virgin olive oil, divided"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "4 Tbsp. unsalted butter, room temperature",
            "treatment": "",
            "note": "",
            "description": "4 Tbsp. unsalted butter, room temperature"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "4 hamburger buns, preferably whole wheat",
            "treatment": "",
            "note": "",
            "description": "4 hamburger buns, preferably whole wheat"
          },
          {
            "unitQuantity": "",
            "unitSize": "",
            "unit": "",
            "ingredientSize": "",
            "name": "4 cups baby arugula",
            "treatment": "",
            "note": "",
            "description": "4 cups baby arugula"
          }
        ]
      }
    ],
    "preparationGroups": [
      {
        "hed": "",
        "steps": [
          {
            "description": "Using your hands, crumble **1¼ lb. ground lamb** into small pieces into a large bowl, scattering in a single layer across bottom and partway up sides of bowl. (This makes it easier to disperse the seasonings evenly without overworking the meat.) Using a Microplane, finely grate **1 lemon** over meat; set lemon aside. Finely grate **2 garlic cloves** into bowl. Sprinkle in **1 tsp. ground coriander**, **1 tsp. Diamond Crystal** or **½ tsp. Morton kosher salt**, and **½ tsp. freshly ground black pepper"
          },
          {
            "description": "Finely chop **¼ cup (packed) cilantro leaves with tender stems** and scatter half over lamb. Set remaining cilantro aside for making yogurt sauce. Toss ground lamb mixture with your hands just until combined—you don\"t want to overwork the meat mixture, otherwise it can become tough. Divide meat into 4 equal portions. Hold 1 portion in the palm of your hand, then gently pat down to make a patty that’s about ¾\"-thick and just a bit wider than your buns (if you have small hands, it might be easier to do this on a cutting board). Place patty on a large plate and repeat with remaining portions.\n\n+++group-2\n\n"
          },
          {
            "description": "Spoon **½ cup plain whole-milk Greek yogurt** into a measuring glass or small bowl. Cut reserved lemon in half, and squeeze juice from 1 half into yogurt. Add **2 Tbsp. extra-virgin olive oil**, **¼ tsp. Diamond Crystal** or **Morton kosher salt**, **¼ tsp. freshly ground black pepper**, and reserved cilantro. Using a small whisk or fork, mix until oil is fully incorporated."
          },
          {
            "description": "Heat a large cast-iron or stainless-steel skillet over medium. Spread **4 Tbsp. room-temperature unsalted butter** over cut sides of **4 hamburger buns**, preferably whole wheat. Working in 2 batches, toast buns, buttered side down, in skillet until golden brown, about 3 minutes. Transfer to plates."
          },
          {
            "description": "Increase heat to medium-high and add **1 Tbsp. extra-virgin olive oil** to skillet. Once oil begins to shimmer, arrange lamb patties in skillet and cook until a dark brown crust forms on bottom side, about 5 minutes. Using a spatula, flip burgers and cook until browned and an instant-read thermometer inserted into the center registers 135° for medium. Transfer to a plate and let rest at least 5 minutes."
          },
          {
            "description": "Place 4 cups baby arugula in a clean large bowl. Drizzle remaining **1 Tbsp. extra-virgin olive oil** over, then squeeze juice from remaining lemon half over. Season with remaining **¼ tsp. Diamond Crystal or Morton kosher salt** and **¼ tsp. freshly ground black pepper** and toss to combine."
          },
          {
            "description": "Spread about 1 Tbsp. yogurt sauce on bottom half of each toasted bun. Top with a small handful of dressed arugula. Place patties on top of arugula. Spread 1 Tbsp. yogurt sauce over patties and close up hamburgers. Serve with remaining arugula salad alongside."
          }
        ],
        "microSteps": []
      }
    ],
    "recipeType": "editorial",
    "photosLede": [
      {
        "type": "photo",
        "id": "5861",
        "altText": "some alt text",
        "caption": "a caption",
        "title": "gartenparty-food.jpg",
        "tags": [],
        "filename": "gartenparty-food.jpg",
        "url": "https://hg-images.condecdn.net/image/oJ0RWZ6DdL3/crop/600/f/apr-10_simple-vanilla-cake_b.jpg",
        "credit": "Pinterest",
        "categories": {}
      }
    ],
    "photosTout": [
      {
        "type": "photo",
        "id": "5861",
        "altText": "some alt text",
        "caption": "a caption",
        "title": "gartenparty-food.jpg",
        "tags": [],
        "filename": "gartenparty-food.jpg",
        "url": "https://hg-images.condecdn.net/image/AX9VnPgbaz2/crop/810/f/chasing-smoke-tahini-bbq-lamb-chops-with-fresh-plums-and-spiced-plum-sauce-patricia-niven.jpg",
        "credit": "Pinterest",
        "categories": {}
      }
    ],
    "photosSocial": [
      {
        "type": "photo",
        "id": "5861",
        "altText": "some alt text",
        "caption": "a caption",
        "title": "gartenparty-food.jpg",
        "tags": [],
        "filename": "gartenparty-food.jpg",
        "url": "https://hg-images.condecdn.net/image/YYnj4KJ1kaQ/crop/810/f/chasing-smoke-tuna-shish-with-chermoula-and-preserved-lemons1.jpg",
        "credit": "Pinterest",
        "categories": {}
      }
    ],
    "publishHistory": {
      "pubDate": "2021-07-04T10:00:00.000Z",
      "searchable": true,
      "uri": "recipe/lamb-burgers-with-yogurt-sauce"
    },
    "categories": {
      "channels": [
        {
          "name": "Category Test",
          "slug": "test",
          "type": "category"
        }
      ],
      "tags": []
    }
  }

Recipe content type

Field Type Required Description Restrictions
type string Yes Content model name Must be recipe
id string Yes Source CMS ID See Resource IDs above
brand string Yes Short hand CNI brand code
lang language tag Yes The language in which the content is written See language tags
hed string Yes The recipe headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
body string Yes The recipe body Copilot flavoured markdown
dek string Yes The recipe subhead Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists. Empty string is allowed
seoTitle string Yes The recipe seo title Plain text
seoCategory string No (default "evergreen") The recipe seo category Must be evergreen or news
seoDescription string Yes The recipe seo description Plain text
tags array of string Yes The recipe tags Array of plain text strings (may be empty). Does not allow duplicates. This field should be restricted to private tags (beginning with _). Public tags (aka "topics") should migrate to categories.tags property.
contentSource string No (default "web") The recipe origin One of digital_syndication, web, magazine, vogue_international or external_agency
canonicalUrl string No The canonical URL of the recipe if sourced from elsewhere Must be a full URL containing http or https
rubric string Yes a 'kicker', A free text category line. Plain text. Empty string is allowed.
socialTitle string Yes The recipe social media title Plain text
socialDescription string Yes The recipe social media description Plain text
photosSocial array of Photo No The recipe social media photo Can contain 0 or 1 image objects
promoHed string No The title shown in teasers (e.g. on index pages) Copilot Limited markdown. Supports Bold, Italic and Strikethrough
promoDek string No The title shown in teasers (e.g. on index pages) Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to this document -
photosLede array of Photo Yes The main photo of the recipe Can contain 0 or 1 image objects, but must not be undefined
videosLede array of CNEVideo No The main video of the recipe Contains 1 CNE video object. Can be empty.
photosTout array of Photo Yes The image shown in teasers (e.g. on index pages) Must contain a min of 1 and a max of 1 image
contributorsAuthor array of Contributor No Byline details of author(s) -
contributorsPhotographer array of Contributor No Details of photographer(s) to be included in byline -
publishHistory object with keys listed below Yes Publication options for the recipe -
publishHistory.pubDate string Yes Publication date ISO 8601 date format
publishHistory.uri string Yes Relative path to published recipe See Relative URIs for accepted pattern
publishHistory.recommendable boolean No (defaults true) If the recipe should appear in recommendations on other recipes -
publishHistory.searchable boolean No (defaults true) If the recipe should appear on index pages -
categories object with the following keys Yes Categories associated with this content Must include sections (on Compass brands) or channels (for all other brands). Other valid keys are listed below
categories.sections array containing a single (sub)section Category Yes (Compass brands) Where in the site nav the content lives Must contain only 1 category. Must include the top level parent section if specifying a subsection.
categories.channels array containing at least one (sub)channel Category Yes (other brands) Where in the site nav the content lives plus other associated (sub)channels Must contain at least one (sub)channel category. Must include the top level parent channel if specifying a subchannel.
categories.tags array of Category No (defaults empty) Public tags (aka "topics") under which this content is indexed Duplicates are not allowed.
categories.functional-tags array of Category No (defaults empty) Private tags for use by the platform associated with this content Duplicates are not allowed. Check to find out what functional tags are supported.
categories.contentWarnings array of Category No (defaults empty) Content warnings for this content Check that Content Warnings are supported before using this. A limited set of content warning categories are allowed. Duplicates are not allowed.
categories.verso-settings array of Category No (defaults empty) Categories to modify the layout of this content in Verso Duplicates are not allowed. The full parent hierarchy should be specified for each setting. Check with the Verso team to find out what settings are supported.
issueDate string No (defaults empty) The recipe issue date
temperatures object with the following keys No Details on Preparation temperatures
temperatures.displayTemp string No (defaults null) Temperature for display
temperatures.preheatTemp number No (defaults null) Pre heat temperature
temperatures.cookingTemp number No (defaults null) Cooking temperature
times object with the following keys No Information relative to the timings
times.displayTime string No (defaults empty) Temperature for display
times.prepTime number No (defaults null) Display time
times.activeTime number No (defaults null) Active time
times.totalTime number No (defaults null) Total time
servingSizeInfo object with the following keys No Details on Timings
servingSizeInfo.servingSizeDescription string No (defaults empty) Service size description
servingSizeInfo.servingSizeUnit string No (defaults empty) Serving size unit
servingSizeInfo.servingSizeRangeFrom number No (defaults null) Serving size range (from)
servingSizeInfo.servingSizeRangeTo number No (defaults null) Serving size range (to)
prepNotes string No (defaults empty) Preparation notes Copilot flavoured markdown
prepNotesHed string No (defaults empty) Preparation notes summary
displayCopyright string No (defaults empty) Display Copyright
copyright string No (defaults empty) Copyright
byline string No (defaults empty) Byline
rotdDate string No (defaults empty) Used for Recipe of the Day module queries. ISO 8601 date format
source string No (defaults empty) Alternate source of the recipe (e.g., Gourmet, Bon Appetit)
amgUserId string No (defaults empty) Member id. Used for member recipes.
isPublic string No (defaults empty) For UGC recipe visibility
recipeType string No (defaults empty) Type Of the following: editorial/member/sponsored
restaurant string No (defaults empty) Restaurant
issueMonth string No (defaults empty) Month of recipe publication.
issueYear number No (defaults null) Year of recipe publication.
ingredientGroups array of ingredientGroup yes A list of ingredients
preparationGroups array of preparationGroup yes A list of preparation steps
inline array of Photo, Embedded Gallery Stub or Embedded Article or Recipe Stub No Photos, articles, recipes and galleries with embedded links in the body -

Ingredient Group

An item of a list of ingredients used in a recipe.

Field Type Required Description Restrictions
hed string No (defaults empty) Summary
ingredients array of ingredient A list of ingredients

Ingredient

A cooking ingredient part of an ingredient group included in a recipe.

Field Type Required Description Restrictions
name string Yes Ingredient name
unit string No (defaults empty) Unit
unitSize string No (defaults empty) Unit size
unitQuantity string No (defaults empty) Unit quantity
ingredientSize string No (defaults empty) Ingredient size
treatment string No (defaults empty) Treatment
description string Yes Description
note string No (defaults empty) Notes

Preparation Group

An item of a list of preparation steps used in a recipe.

Field Type Required Description Restrictions
hed string No (defaults empty) Summary
steps array of preparation steps A list of preparation steps
microSteps array of preparation steps A list of preparation micro steps

Preparation Step

A preparation step included in a preparation group used in a recipe.

Field Type Required Description Restrictions
description string Yes Decription of the recipe preparation step Copilot Limited markdown. Supports Bold, Italic and Strikethrough

Native Recipe

Sample native recipe

  {
    "type": "nativerecipe",
    "id": "native-recipe-1",
    "brand": "lci",
    "lang": "en-US",
    "self": "/nativerecipes/native-recipe-1",
    "body": "Lamb, lemon, cilantro, arugula—in our house, these ingredients scream summer, so it seemed natural to combine them, along with a few other ingredients, to make a burger with a bright, citrusy yogurt sauce. The arugula does double duty as a topping and a side salad, keeping this meal quick, easy, and light. My partner and I found this burger doesn’t need cheese, but if you feel compelled to add it, it pairs particularly well with nutty, earthy cheeses like sheep’s-milk Gouda, aged cow’s milk Gouda, and Manchego, though you will only need half as much yogurt sauce. *—Jarrett Melendez*",
    "canonicalUrl": "",
    "contentSource": "web",
    "dek": "Some recipe dek",
    "hed": "Some recipe hed",
    "issueDate": "",
    "promoDek": "This flavorful lamb patty with lemony yogurt sauce is guaranteed to spice up your burger routine. ",
    "promoHed": "Lamb Burgers With Yogurt Sauce and Arugula",
    "seoDescription": "This flavorful lamb patty with lemony yogurt sauce is guaranteed to spice up your burger routine. ",
    "seoTitle": "Lamb Burgers With Yogurt Sauce and Arugula",
    "socialDescription": "This flavorful lamb patty with lemony yogurt sauce is guaranteed to spice up your burger routine. ",
    "socialTitle": "Lamb Burgers With Yogurt Sauce and Arugula",
    "tags": [],
    "temperatures": {
      "displayTemp": "",
      "preheatTemp": null,
      "cookingTemp": null
    },
    "times": {
      "displayTime": "",
      "prepTime": "",
      "activeTime": "",
      "totalTime": ""
    },
    "servingSizeInfo": {
      "servingSizeDescription": "4 servings",
      "servingSizeUnit": "",
      "servingSizeRangeFrom": null,
      "servingSizeRangeTo": null
    },
    "prepNotes": "",
    "prepNotesHed": "",
    "byline": "",
    "source": "",
    "amgUserId": "",
    "isPublic": true,
    "restaurant": "",
    "issueMonth": "July",
    "issueYear": 2021,
    "ingredientGroups": [
      {
        "ingredients": [
          {
            "name": "1¼ lb. ground lamb",
            "description": "1¼ lb. ground lamb"
          },
          {
            "name": "1 lemon",
            "description": "1 lemon"
          },
          {
            "name": "2 garlic cloves",
            "description": "2 garlic cloves"
          },
          {
            "name": "1 tsp. ground coriander",
            "description": "1 tsp. ground coriander"
          },
          {
            "name": "1½ tsp. Diamond Crystal or 1 tsp. Morton kosher salt, divided",
            "description": "1½ tsp. Diamond Crystal or 1 tsp. Morton kosher salt, divided"
          },
          {
            "name": "1 tsp. freshly ground black pepper, divided",
            "description": "1 tsp. freshly ground black pepper, divided"
          },
          {
            "name": "¼ cup (packed) cilantro leaves with tender stems",
            "description": "¼ cup (packed) cilantro leaves with tender stems"
          },
          {
            "name": "½ cup plain whole-milk Greek yogurt",
            "description": "½ cup plain whole-milk Greek yogurt"
          },
          {
            "name": "4 Tbsp. extra-virgin olive oil, divided",
            "description": "4 Tbsp. extra-virgin olive oil, divided"
          },
          {
            "name": "4 Tbsp. unsalted butter, room temperature",
            "description": "4 Tbsp. unsalted butter, room temperature"
          },
          {
            "name": "4 hamburger buns, preferably whole wheat",
            "description": "4 hamburger buns, preferably whole wheat"
          },
          {
            "name": "4 cups baby arugula",
            "description": "4 cups baby arugula"
          }
        ]
      }
    ],
    "preparationGroups": [
      {
        "hed": "",
        "steps": [
          {
            "description": "Using your hands, crumble **1¼ lb. ground lamb** into small pieces into a large bowl, scattering in a single layer across bottom and partway up sides of bowl. (This makes it easier to disperse the seasonings evenly without overworking the meat.) Using a Microplane, finely grate **1 lemon** over meat; set lemon aside. Finely grate **2 garlic cloves** into bowl. Sprinkle in **1 tsp. ground coriander**, **1 tsp. Diamond Crystal** or **½ tsp. Morton kosher salt**, and **½ tsp. freshly ground black pepper"
          },
          {
            "description": "Finely chop **¼ cup (packed) cilantro leaves with tender stems** and scatter half over lamb. Set remaining cilantro aside for making yogurt sauce. Toss ground lamb mixture with your hands just until combined—you don\"t want to overwork the meat mixture, otherwise it can become tough. Divide meat into 4 equal portions. Hold 1 portion in the palm of your hand, then gently pat down to make a patty that’s about ¾\"-thick and just a bit wider than your buns (if you have small hands, it might be easier to do this on a cutting board). Place patty on a large plate and repeat with remaining portions.\n\n+++group-2\n\n"
          },
          {
            "description": "Spoon **½ cup plain whole-milk Greek yogurt** into a measuring glass or small bowl. Cut reserved lemon in half, and squeeze juice from 1 half into yogurt. Add **2 Tbsp. extra-virgin olive oil**, **¼ tsp. Diamond Crystal** or **Morton kosher salt**, **¼ tsp. freshly ground black pepper**, and reserved cilantro. Using a small whisk or fork, mix until oil is fully incorporated."
          },
          {
            "description": "Heat a large cast-iron or stainless-steel skillet over medium. Spread **4 Tbsp. room-temperature unsalted butter** over cut sides of **4 hamburger buns**, preferably whole wheat. Working in 2 batches, toast buns, buttered side down, in skillet until golden brown, about 3 minutes. Transfer to plates."
          },
          {
            "description": "Increase heat to medium-high and add **1 Tbsp. extra-virgin olive oil** to skillet. Once oil begins to shimmer, arrange lamb patties in skillet and cook until a dark brown crust forms on bottom side, about 5 minutes. Using a spatula, flip burgers and cook until browned and an instant-read thermometer inserted into the center registers 135° for medium. Transfer to a plate and let rest at least 5 minutes."
          },
          {
            "description": "Place 4 cups baby arugula in a clean large bowl. Drizzle remaining **1 Tbsp. extra-virgin olive oil** over, then squeeze juice from remaining lemon half over. Season with remaining **¼ tsp. Diamond Crystal or Morton kosher salt** and **¼ tsp. freshly ground black pepper** and toss to combine."
          },
          {
            "description": "Spread about 1 Tbsp. yogurt sauce on bottom half of each toasted bun. Top with a small handful of dressed arugula. Place patties on top of arugula. Spread 1 Tbsp. yogurt sauce over patties and close up hamburgers. Serve with remaining arugula salad alongside."
          }
        ],
        "microSteps": []
      }
    ],
    "recipeType": "editorial",
    "photosLede": [
      {
        "type": "photo",
        "id": "5861",
        "altText": "some alt text",
        "caption": "a caption",
        "title": "gartenparty-food.jpg",
        "tags": [],
        "filename": "gartenparty-food.jpg",
        "url": "https://hg-images.condecdn.net/image/oJ0RWZ6DdL3/crop/600/f/apr-10_simple-vanilla-cake_b.jpg",
        "credit": "Pinterest",
        "categories": {}
      }
    ],
    "photosTout": [
      {
        "type": "photo",
        "id": "5861",
        "altText": "some alt text",
        "caption": "a caption",
        "title": "gartenparty-food.jpg",
        "tags": [],
        "filename": "gartenparty-food.jpg",
        "url": "https://hg-images.condecdn.net/image/AX9VnPgbaz2/crop/810/f/chasing-smoke-tahini-bbq-lamb-chops-with-fresh-plums-and-spiced-plum-sauce-patricia-niven.jpg",
        "credit": "Pinterest",
        "categories": {}
      }
    ],
    "photosSocial": [
      {
        "type": "photo",
        "id": "5861",
        "altText": "some alt text",
        "caption": "a caption",
        "title": "gartenparty-food.jpg",
        "tags": [],
        "filename": "gartenparty-food.jpg",
        "url": "https://hg-images.condecdn.net/image/YYnj4KJ1kaQ/crop/810/f/chasing-smoke-tuna-shish-with-chermoula-and-preserved-lemons1.jpg",
        "credit": "Pinterest",
        "categories": {}
      }
    ],
    "publishHistory": {
      "pubDate": "2021-07-04T10:00:00.000Z",
      "searchable": true,
      "uri": "native-recipe/lamb-burgers-with-yogurt-sauce"
    },
    "categories": {
      "channels": [
        {
          "name": "Recipes",
          "slug": "recipes",
          "type": "category"
        }
      ],
      "tags": []
    }
  }

Native recipe content type used for publishing advertiser sponsored recipes

Field Type Required Description Restrictions
type string Yes Content model name Must be nativerecipe
id string Yes Source CMS ID See Resource IDs above
brand string Yes Short hand CNI brand code
lang language tag Yes The language in which the content is written See language tags
hed string Yes The recipe headline Copilot Limited markdown. Supports Bold, Italic and Strikethrough
body string Yes The recipe body Copilot flavoured markdown
dek string Yes The recipe subhead Copilot Limited markdown. Supports Bold, Italic, Strikethrough, Link and Lists. Empty string is allowed
bylineOption string No (default "produced") The advertiser byline wording option See native byline options.
bylineVariant string No (see Notes) The advertiser byline variation (whether to show logo) Either logo (default if advertiser has logo) or text (default if advertiser has no logo)
campaignUrl string Yes The sponsored campaign url URL
advertiser Advertiser Yes The advertiser to link this article to -
seoTitle string Yes The recipe seo title Plain text
seoCategory string No (default "evergreen") The recipe seo category Must be evergreen or news
seoDescription string Yes The recipe seo description Plain text
tags array of string Yes The recipe tags Array of plain text strings (may be empty). Does not allow duplicates. This field should be restricted to private tags (beginning with _). Public tags (aka "topics") should migrate to categories.tags property.
contentSource string No (default "web") The recipe origin One of digital_syndication, web, magazine, vogue_international or external_agency
canonicalUrl string No The canonical URL of the recipe if sourced from elsewhere Must be a full URL containing http or https
rubric string Yes a 'kicker', A free text category line. Plain text. Empty string is allowed.
socialTitle string Yes The recipe social media title Plain text
socialDescription string Yes The recipe social media description Plain text
photosSocial array of Photo No The recipe social media photo Can contain 0 or 1 image objects
promoHed string No The title shown in teasers (e.g. on index pages) Copilot Limited markdown. Supports Bold, Italic and Strikethrough
promoDek string No The title shown in teasers (e.g. on index pages) Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to this document -
photosLede array of Photo Yes The main photo of the recipe Can contain 0 or 1 image objects, but must not be undefined
videosLede array of CNEVideo No The main video of the recipe Contains 1 CNE video object. Can be empty.
photosTout array of Photo Yes The image shown in teasers (e.g. on index pages) Must contain a min of 1 and a max of 1 image
contributorsAuthor array of Contributor No Byline details of author(s) -
contributorsPhotographer array of Contributor No Details of photographer(s) to be included in byline -
publishHistory object with keys listed below Yes Publication options for the recipe -
publishHistory.pubDate string Yes Publication date ISO 8601 date format
publishHistory.uri string Yes Relative path to published recipe See Relative URIs for accepted pattern
publishHistory.recommendable boolean No (defaults true) If the recipe should appear in recommendations on other recipes -
publishHistory.searchable boolean No (defaults true) If the recipe should appear on index pages -
categories object with the following keys Yes Categories associated with this content Must include sections (on Compass brands) or channels (for all other brands). Other valid keys are listed below
categories.sections array containing a single (sub)section Category Yes (Compass brands) Where in the site nav the content lives Must contain only 1 category. Must include the top level parent section if specifying a subsection.
categories.channels array containing at least one (sub)channel Category Yes (other brands) Where in the site nav the content lives plus other associated (sub)channels Must contain at least one (sub)channel category. Must include the top level parent channel if specifying a subchannel.
categories.tags array of Category No (defaults empty) Public tags (aka "topics") under which this content is indexed Duplicates are not allowed.
categories.functional-tags array of Category No (defaults empty) Private tags for use by the platform associated with this content Duplicates are not allowed. Check to find out what functional tags are supported.
categories.contentWarnings array of Category No (defaults empty) Content warnings for this content Check that Content Warnings are supported before using this. A limited set of content warning categories are allowed. Duplicates are not allowed.
categories.verso-settings array of Category No (defaults empty) Categories to modify the layout of this content in Verso Duplicates are not allowed. The full parent hierarchy should be specified for each setting. Check with the Verso team to find out what settings are supported.
issueDate string No (defaults empty) The recipe issue date
temperatures object with the following keys No Details on Preparation temperatures
temperatures.displayTemp string No (defaults null) Temperature for display
temperatures.preheatTemp number No (defaults null) Pre heat temperature
temperatures.cookingTemp number No (defaults null) Cooking temperature
times object with the following keys No Information relative to the timings
times.displayTime string No (defaults empty) Temperature for display
times.prepTime number No (defaults null) Display time
times.activeTime number No (defaults null) Active time
times.totalTime number No (defaults null) Total time
servingSizeInfo object with the following keys No Details on Timings
servingSizeInfo.servingSizeDescription string No (defaults empty) Service size description
servingSizeInfo.servingSizeUnit string No (defaults empty) Serving size unit
servingSizeInfo.servingSizeRangeFrom number No (defaults null) Serving size range (from)
servingSizeInfo.servingSizeRangeTo number No (defaults null) Serving size range (to)
prepNotes string No (defaults empty) Preparation notes Copilot flavoured markdown
prepNotesHed string No (defaults empty) Preparation notes summary
displayCopyright string No (defaults empty) Display Copyright
copyright string No (defaults empty) Copyright
byline string No (defaults empty) Byline
rotdDate string No (defaults empty) Used for Recipe of the Day module queries. ISO 8601 date format
source string No (defaults empty) Alternate source of the recipe (e.g., Gourmet, Bon Appetit)
amgUserId string No (defaults empty) Member id. Used for member recipes.
isPublic string No (defaults empty) For UGC recipe visibility
recipeType string No (defaults empty) Type Of the following: editorial/member/sponsored
restaurant string No (defaults empty) Restaurant
issueMonth string No (defaults empty) Month of recipe publication.
issueYear number No (defaults null) Year of recipe publication.
ingredientGroups array of ingredientGroup yes A list of ingredients
preparationGroups array of preparationGroup yes A list of preparation steps
inline array of Photo, Embedded Gallery Stub or Embedded Article or Recipe Stub No Photos, articles, recipes and galleries with embedded links in the body -

Hotel

Sample hotel

Warning: The hotel content type is only available for CNT brands.

  {
    "brand": "cnt",
    "lang": "en-US",
    "type": "hotel",
    "name": "Hotel Soho Barcelona",
    "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
    "description": "Situated on the busy Gran Via, the elegant Hotel Soho is a ten-minute walk from the Plaça Catalunya. Designed by local architect Alfredo Arribas, the minimalist look features designer frills such as Verner Panton lamps, super-comfortable beds, and natty glassed-in bathrooms. The best rooms are on the seventh floor and come with wood-decked terraces. There's no restaurant, but breakfast is served in the lobby and room service is available until 9 p.m. A snazzy business center in the basement and a cool rooftop plunge pool make the place a bargain. __Strengths__: Excellent location; great style. __Weaknesses__: Heavy traffic on the Gran Via means rooms on the lower floors can be noisy.",
    "self": "/hotels/hotel-id-1",
    "contributorsAuthor": ["..."],
    "contributorsPhotographer": [],
    "id": "hotel-id-1",
    "seoTitle": "Some SEO title",
    "seoDescription": "Some SEO Description",
    "photosTout": [
      {
        "type": "photo",
        "id": "586e",
        "inlineHref": "/photos/586e",
        "altText": "some alt text",
        "caption": "a caption",
        "title": "gartenparty-food.jpg",
        "tags": [],
        "filename": "gartenparty-food.jpg",
        "url": "https://flyway-api-demo.example.com/public/images/586d_gartenparty-food.jpg",
        "credit": "Pinterest",
        "categories": {}
      }
    ],
    "photosLede": [
      {
        "type": "photo",
        "id": "586e",
        "inlineHref": "/photos/586e",
        "altText": "some alt text",
        "caption": "a caption",
        "title": "gartenparty-food.jpg",
        "tags": [],
        "filename": "gartenparty-food.jpg",
        "url": "https://flyway-api-demo.example.com/public/images/586d_gartenparty-food.jpg",
        "credit": "Pinterest",
        "categories": {}
      }
    ],
    "photosSocial": [
      {
        "type": "photo",
        "id": "586e",
        "inlineHref": "/photos/586e",
        "altText": "some alt text",
        "caption": "a caption",
        "title": "gartenparty-food.jpg",
        "tags": [],
        "filename": "gartenparty-food.jpg",
        "url": "https://flyway-api-demo.example.com/public/images/586d_gartenparty-food.jpg",
        "credit": "Pinterest",
        "categories": {}
      }
    ],

    "url": ["http://www.hotelsohobarcelona.com/default-en.html"],
    "email": ["soho@nnhotels.com"],
    "geo": {
      "lat": 41.3834388,
      "lng": 2.1598504
    },
    "region": "Europe", 
    "phone": ["+34 93-552-96-10"],
    "address": {
      "street": "Gran Via de les Corts Catalanes 543-545",
      "state": "",
      "city": "Barcelona",
      "country": "Spain",
      "postalCode": "08011"
    },
    "subtype": "Hotel",
    "price": 1,

    "ratingBlock": {
      "overall": 5
    },
    "categories": {
      "channels": [
        {
          "type": "category",
          "slug": "lifestyle",
          "name": "Lifestyle"
        }
      ],
      "tags": [
        {
          "type": "category",
          "slug": "party-looks",
          "name": "Party-Looks"
        },
        {
          "type": "category",
          "slug": "partys",
          "name": "Partys"
        },
        {
          "type": "category",
          "slug": "sommertrends",
          "name": "Sommertrends"
        }
      ],
      "contentWarnings": [
        {
          "type": "category",
          "slug": "sexual_content",
          "name": "Sex content"
        },
        {
          "type": "category",
          "slug": "alcohol_content",
          "name": "Alcohol content"
        }
      ]
    },
    "tags": ["_private:tag"],
    "publishHistory": {
      "pubDate": "2015-03-09T20:52:36.322Z",
      "uri": "hotels/barcelona/hotel-soho-barcelona"
    }
  }

Hotel content type

Field Type Required Description Restrictions
type string Yes Content model name Must be hotel
id string Yes Source CMS ID See Resource IDs above
brand string Yes Short hand CNI brand code Must be a CNT brand
lang language tag Yes The language in which the content is written See language tags
body string Yes Body Copilot flavoured markdown
description string No A description of the hotel Copilot flavoured markdown
name string Yes Hotel name Plain text
seoTitle string Yes SEO title Plain text
seoCategory string No (default "evergreen") SEO category Must be evergreen or news
seoDescription string Yes SEO description Plain text
tags array of string Yes The hotel tags Array of plain text strings (may be empty). Does not allow duplicates. This field should be restricted to private tags (beginning with _). Public tags (aka "topics") should migrate to categories.tags property.
contentSource string No (default "web") Origin One of digital_syndication, web, magazine, vogue_international or external_agency
canonicalUrl string No The canonical URL of the hotel if sourced from elsewhere Must be a full URL containing http or https
socialTitle string Yes Social media title Plain text
socialDescription string Yes The hotel social media description Plain text
promoHed string No The title shown in teasers (e.g. on index pages) Copilot Limited markdown. Supports Bold, Italic and Strikethrough
promoDek string No The title shown in teasers (e.g. on index pages) Copilot Limited markdown. Supports Bold, Italic and Strikethrough
self Links Yes Contains a link to this document -
contributorsAuthor array of Contributor No Byline details of author(s) -
contributorsPhotographer array of Contributor No Details of photographer(s) to be included in byline -
photosLede array of Photo Yes The main photo of the hotel Can contain 0 or 1 image objects, but must not be undefined
photosTout array of Photo Yes The image shown in teasers (e.g. on index pages) Must contain a min of 1 and a max of 1 image
photosSocial array of Photo No The hotel social media photo Can contain 0 or 1 image objects
url array of strings No A list of the hotel URLs Plain text
phone array of strings No A list of the hotel phone numbers Plain text
description string No A description of the hotel Plain text
email array of strings No A list of the hotel email addresses must be a valid email address
address object with keys listed below Yes Hotel address -
address.street string No Hotel street -
address.streetExtended string No Hotel street - extended -
address.locality string No Hotel locality -
address.city string No Hotel city -
address.state string No Hotel state -
address.country string No Hotel country -
address.postalCode string No Hotel postal code -
region string Yes Region Must be one of the following: Africa, Asia, Australia/Pacific, Canada, Caribbean/Atlantic, Central America, Europe, Indian Ocean, Mexico, Middle East, South America, United States
geo object with keys listed below Yes Hotel coordinates -
geo.lat string Yes Latitude -
geo.lng string Yes Longitude -
subType string Yes The type of Hotel Must be one of the following: Hotel, Resort, Bed and Breakfast, Private Rental, Destination Spa, Boutique
price Number No An index of the hotel price range Must be minimum: 0, maximum 3
ratingBlock Number No Hotel rating
categories object with the following keys Yes Categories associated with this content Must include sections (on Compass brands) or channels (for all other brands). Other valid keys are listed below
categories.sections array containing a single (sub)section Category Yes (Compass brands) Where in the site nav the content lives Must contain only 1 category. Must include the top level parent section if specifying a subsection.
categories.channels array containing at least one (sub)channel Category Yes (other brands) Where in the site nav the content lives plus other associated (sub)channels Must contain at least one (sub)channel category. Must include the top level parent channel if specifying a subchannel.
categories.tags array of Category No (defaults empty) Public tags (aka "topics") under which this content is indexed Duplicates are not allowed.
categories.functional-tags array of Category No (defaults empty) Private tags for use by the platform associated with this content Duplicates are not allowed. Check to find out what functional tags are supported.
categories.contentWarnings array of Category No (defaults empty) Content warnings for this content Check that Content Warnings are supported before using this. A limited set of content warning categories are allowed. Duplicates are not allowed.
categories.verso-settings array of Category No (defaults empty) Categories to modify the layout of this content in Verso Duplicates are not allowed. The full parent hierarchy should be specified for each setting. Check with the Verso team to find out what settings are supported.
inline array of Photo, Gallery or Embedded Article Stub No Photos, articles and galleries with embedded links in the body -

Content API

Get All Entities

curl "http://flyway-api-demo.example.com/api/entities"

The above command returns a JSON structured mixed response containing standard and native articles, as well as galleries

{
  "page": 1,
  "totalCount": 12,
  "brand": "dmo",
  "self": "http://flyway-api-demo.example.com/api/entities",
  "next":  "http://flyway-api-demo.example.com/api/entities?page=2",
  "hasMore": true,
  "data": [
    {
      "hed": "Hi, I'm an article on page 1 of a paginated list",
      "id": 1,
      "self": "http://flyway-api-demo.example.com/api/articles/1",
      "type": "article"
    },
    {
      "hed": "Hi, I'm a gallery on page 1 of a paginated list",
      "id": 2,
      "self": "http://flyway-api-demo.example.com/api/galleries/2",
      "type": "gallery"
    },
    // Snip,
    {
      "hed": "Hi, I'm an article on page 1 of a paginated list",
      "id": 9,
      "self": "http://flyway-api-demo.example.com/api/articles/9",
      "type": "article"
    },
    {
      "hed": "Hi, I'm a gallery on page 1 of a paginated list",
      "id": 10,
      "self": "http://flyway-api-demo.example.com/api/galleries/10",
      "type": "gallery"
    }
  ]
}

This endpoint can be used a single endpoint that returns all entities together. The response follows the pagination scheme laid out above. A similar separate endpoint may also be provided for retrieving galleries, articles, and native articles.

HTTP Request

GET /api/entities

Query Parameters

In addition to the default pagination query parameters the integration API may support additional query parameters that allow the results to be restricted, for example by category or tag. This is entirely optional and any supported parameters and their names are up to the implementers. Any additional parameters should be preserved in the next and prev links so that pagination works across the full restricted query results.

It will be possible to start a migration in Flyway of a subset of entities by specifying any additional query parameters that are supported by the integration API.

Response

A paginated response containing items of type article, nativearticle, gallery, or a combination of all three.

All entities in the response must include the following fields:

Field Description
id the entity ID in the integration system
type always article or nativearticle or gallery
self a link which must contain the URL to retrieve the fully hydrated entity

Other fields from the full article/gallery response may be included. These will not be used by Flyway but can help with diagnostics and human readability.

Get All Articles

curl "http://flyway-api-demo.example.com/api/articles"

The above command returns JSON structured like this:

{
  "page": 1,
  "totalCount": 12,
  "brand": "dmo",
  "self": "http://flyway-api-demo.example.com/api/articles",
  "next":  "http://flyway-api-demo.example.com/api/articles?page=2",
  "hasMore": true,
  "data": [
    {
      "hed": "Hi, I'm an article on page 1 of a paginated list",
      "id": 1,
      "self": "http://flyway-api-demo.example.com/api/articles/1",
      "type": "article"
    },
    {
      "hed": "Hi, I'm an article on page 1 of a paginated list",
      "id": 2,
      "self": "http://flyway-api-demo.example.com/api/articles/2",
      "type": "article"
    },
    // Snip,
    {
      "hed": "Hi, I'm an article on page 1 of a paginated list",
      "id": 9,
      "self": "http://flyway-api-demo.example.com/api/articles/9",
      "type": "article"
    },
    {
      "hed": "Hi, I'm an article on page 1 of a paginated list",
      "id": 10,
      "self": "http://flyway-api-demo.example.com/api/articles/10",
      "type": "article"
    }
  ]
}

Example mixed response containing both standard and native articles

{
  "page": 1,
  "totalCount": 999,
  "brand": "dmo",
  "self": "http://flyway-api-demo.example.com/api/articles",
  "next":  "http://flyway-api-demo.example.com/api/articles?page=2",
  "hasMore": true,
  "data": [
    {
      "hed": "An article on page 1 of a paginated list",
      "id": 1,
      "self": "http://flyway-api-demo.example.com/api/articles/1",
      "type": "article"
    },
    {
      "hed": "A native article on page 1 of a paginated list",
      "id": 2,
      "self": "http://flyway-api-demo.example.com/api/nativearticles/2",
      "type": "nativearticle"
    },
    {
      "hed": "Another article on page 1 of a paginated list",
      "id": 3,
      "self": "http://flyway-api-demo.example.com/api/articles/3",
      "type": "article"
    }
  ]
}

This endpoint retrieves all articles. The response follows the pagination scheme laid out above. A similar endpoint may be provided for retrieving native articles. Or you may provide a single endpoint that returns all standard and native articles together.

HTTP Request

GET /api/articles

If providing a separate endpoint for native articles, we suggest GET /api/nativearticles.

Query Parameters

In addition to the default pagination query parameters the integration API may support additional query parameters that allow the results to be restricted, for example by category or tag. This is entirely optional and any supported parameters and their names are up to the implementers. Any additional parameters should be preserved in the next and prev links so that pagination works across the full restricted query results.

It will be possible to start a migration in Flyway of a subset of articles by specifying any additional query parameters that are supported by the integration API.

Response

A paginated response containing items of type article, nativearticle or both.

All articles in the response must include the following fields:

Field Description
id the article ID in the integration system
type always article or nativearticle
self a link which must contain the URL to retrieve the fully hydrated article

Other fields from the full article response may be included. These will not be used by Flyway but can help with diagnostics and human readability.

Get Article

curl "http://flyway-api-demo.example.com/api/articles/2"

The above command returns JSON structured like this:

{
  "type": "article",
  "id": "6dfd",
  "brand": "dmo",
  "lang": "de-DE",
  "hed": "Der große VOGUE-Gartenparty-Guide",
  "body": "\n## Die perfekte Location\nFür eine Gartenparty ist es natürlich von Vorteil, einen Garten zu haben, klar. Am besten mit einer Hängematte, die idyllisch zwischen zwei alten Kirschbäumen aufgehängt ist und einer mit Gänseblümchen übersäten Wiese. Wer dieses Glück nicht hat, muss aber nicht gleich alle Pläne über Bord werfen. Die neue Art des Feierns ist ungezwungen, locker und leicht.\n\nSo leger, dass die Sommerparty auch auf den Balkon verlagert werden kann. Oder in ein nahegelegenes Feld. Oder einen Schrebergarten – der feiert 2017 nämlich ein großes Comeback!. Was nicht passt, wird also passend gemacht. Und zwar mit der richtigen Dekoration, Punkt zwei auf der Organisations-Liste.\n\n\n\n[#image: /photos/c991]\n\n\n## Tischlein, deck dich!\nFür die Tischdekoration kann man sich im Vorfeld ein grobes Konzept überlegen: Vintage-Charme, romantischer Blütentraum, Boho-Chic oder schlichte Eleganz? Nach diesen Überlegungen geht es an die Details: Eine helle Tischdecke oder ein alter Holztisch dienen als Leinwand für die Dekoration. Schon Stoffservietten und Lampions schaffen Atmosphäre. Mit Kerzen in verschiedenen Größen und bunten Girlanden können Sommertisch und Umgebung noch ideenreicher geschmückt werden.\n\nWenn man an den Sommer denkt, kommen einem sofort Blumen in den Sinn. Blumen machen gute Laune, sei es auf dem Tisch oder als Dekoration im Aperitif. Besonders schön kommen die Blüten zur Geltung, wenn sie in Einweckgläsern, kleinen Vasen oder Apothekerbehältnissen überall auf dem Tisch verteilt werden. Um noch mehr sommerlichen Flair in den Garten zu holen, eignen sich viele verschiedene Blumen wie Ranunkeln, Pfingstrosen, Lilien, Flieder und Schleierkraut. Einen Wow-Effekt während des Aperitifs erzielen Eiswürfel, in denen eine Blüte eingefroren wurde. Wem mehr nach etwas *Dolce Vita* im heimischen Garten ist, setzt auf eine mediterrane Deko und arrangiert Zitronen, Orangen und Olivenzweige in der Tischmitte.\n\nUnd wer nicht genügend Gartenstühle für die Gäste zur Verfügung stehen hat, sammelt einfach alle Sitzmöglichkeiten von drinnen ein – der Möbel-Mix wirkt umso gemütlicher. Auch Kissen und Decken tragen zur Wohlfühlatmosphäre bei. \n\n\n\n[#image: /photos/5ab1]\n\n\n## Soulfood für die Gartenparty\nAn lauen Sommerabenden gibt es doch nichts Besseres als knackige [Salate](http://www.vogue.de/gourmet/salat-rezepte-hemsley-hemsley), frische [Limonaden](http://www.vogue.de/gourmet/rezepte/tea-time-rooibos-grapefruit-eistee) und leichte Vorspeisen, die sich jeder Gast individuell zusammenstellen kann. Spritzige Aperitifs wie Hugo, Inge (mit Ingwer) oder Lillet Berry (mit Lillet und Schweppes Wild Berry) und Wasserkaraffen, angereichert mit frischen Kräutern und Früchten, eignen sich hervorragend für Gartenpartys – und sehen dabei dekorativ aus. Mit einigen Weinkisten kann man sich eine eigene Bar schreinern, an der sich die Gäste selbst bedienen – und ihr eigenes Sommergetränk mischen können. Und auch für das leibliche Wohl soll gesorgt sein: Ganz entspannt und schnell vorbereitet sind unsere sieben Lieblingsideen für die Gartenparty-Seelenkost.\n\n\n\n[#image: /photos/586e]\n\n\n## Lieblingssnacks\n\n\n1.    [Erfrischender Orangensalat](http://www.vogue.de/gourmet/rezepte/vegetarische-koestlichkeiten-orangensalat)\n\n\n2.    [Feigen mit Büffelmozzarella](http://www.vogue.de/gourmet/rezepte/feigen-bueffelmozzarella)\n\n\n3.    [Hähnchen-Aprikosen-Spieße](http://www.vogue.de/gourmet/rezepte/haehnchen-aprikosen-spiesse)\n\n\n4.    [Melonensalat mit Minze](http://www.vogue.de/gourmet/rezepte/melonensalat-rezept)\n\n\n5.    [Gekühlte Tomaten-Pfirsich-Suppe](http://www.vogue.de/gourmet/rezepte/kalte-tomaten-pfirsich-suppe)\n\n\n6.    [Gegrillte Käse-Fladenbrote mit Feigen](http://www.vogue.de/gourmet/rezepte/fladenbrot-kaese-grillen)\n\n\n7.    [Erdbeer-Tartes mit Ingwer-Nuss-Boden](http://www.vogue.de/gourmet/rezepte/erdbeer-tartes-mit-ingwer-nuss-boden)       \n\n\n\n\n## Sommersounds auf der Gartenparty\nWas wäre eine Party ohne Musik? Das hier sind die Lieblingssongs des Sommers 2017 der Spotify-User:\n\n\n\n## Dresscode: Sommer, bitte!\nEtwas Grandezza, bitte sehr! Mit den Kleidertrends 2017 kann man sich sommerliche Eleganz ganz einfach in den Garten holen. Kleider reichen in diesem Sommer von folkloristischen Kaftans über Hemdblusenkleider bis hin zu floralen Midi-Kleidern. Und auch das perfekte weiße Kleid ist eine sichere Variante für jede Sommerparty. Der Trend *Basket Bag* *–* also ein kleiner geflochtener Korb statt Handtasche – passt ebenso hervorragend in die Kulisse. Da der Teint im Sommer kaum Make-up benötigt, wird ein natürlicher Glow mit etwas Blush auf den Wangen und mit dem Finger aufgetupftem Gloss auf den Lippen erzielt – that's it. Wer eine \"Save the date\"-Einladungskarte vorbereitet, kann den Dresscode einfach darauf vermerken. Und nun? Lasset die Gartenparty beginnen!\n\n\n\n[#instagram: https://www.instagram.com/p/BVDHlPQFOKw/]\n\n\n\n",
  "dek": "Tanzen unter Sternenhimmel, Sommerklänge und Soulfood: Es ist die Ungezwungenheit, die das Feiern im Freien so besonders macht. So gelingt die perfekte Gartenparty mit ein paar Handgriffen und DIY-Ideen garantiert. Worauf warten Sie noch? Auf drei geht's los! \r\n",
  "seoTitle": "Der große VOGUE-Gartenparty-Guide",
  "seoDescription": "So gelingt die perfekte Gartenparty mit ein paar Handgriffen und DIY-Ideen! Worauf warten Sie noch? Auf drei geht's los! \r\n",
  "tags": [
    "Party-Looks",
    "Partys",
    "Sommertrends"
  ],
  "rubric": "Die perfekte Feier ",
  "ledeCaption": "",
  "socialTitle": "Der große VOGUE-Gartenparty-Guide",
  "socialDescription": "So gelingt die perfekte Gartenparty ",
  "promoHed": "Der große VOGUE-Gartenparty-Guide",
  "self": "https://flyway-api-demo.example.com/api/articles/6dfd",
  "photosTout": [
    {
      "type": "photo",
      "id": "34c6",
      "credit": "Pinterest (3); Collage: Condé Nast",
      "filename": "gartenparty-tischdekoration-blumen.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/34c5_gartenparty-tischdekoration-blumen.jpg",
      "tags": [],
      "caption": "",
      "title": "gartenparty-tischdekoration-blumen.jpg"
    }
  ],
  "photosLede": [
    {
      "type": "photo",
      "id": "34c6",
      "credit": "Pinterest (3); Collage: Condé Nast",
      "filename": "gartenparty-tischdekoration-blumen.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/34c5_gartenparty-tischdekoration-blumen.jpg",
      "tags": [],
      "caption": "",
      "title": "gartenparty-tischdekoration-blumen.jpg"
    }
  ],
  "photosSocial": [
    {
      "type": "photo",
      "id": "34c6",
      "credit": "Pinterest (3); Collage: Condé Nast",
      "filename": "gartenparty-tischdekoration-blumen.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/34c5_gartenparty-tischdekoration-blumen.jpg",
      "tags": [],
      "caption": "",
      "title": "gartenparty-tischdekoration-blumen.jpg"
    }
  ],
  "contributorsAuthor": [
    {
      "type": "contributor",
      "id": "c3c7",
      "name": "Jana Ackermann",
      "tags": [],
      "uri": "die-redaktion/jana-ackermann"
    }
  ],
  "inline": [
    {
      "type": "photo",
      "id": "586e",
      "title": "gartenparty-food.jpg",
      "tags": [],
      "filename": "gartenparty-food.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/586d_gartenparty-food.jpg",
      "altText": "",
      "credit": "Pinterest",
      "caption": ""
    },
    {
      "type": "photo",
      "id": "c991",
      "title": "gartenparty-pinterest.jpg",
      "tags": [],
      "filename": "gartenparty-pinterest.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/c990_gartenparty-pinterest.jpg",
      "altText": "",
      "credit": "Pinterest",
      "caption": ""
    },
    {
      "type": "photo",
      "id": "5ab1",
      "title": "gartenparty-tischdekoration-blumen.jpg",
      "tags": [],
      "filename": "gartenparty-tischdekoration-blumen.jpg",
      "altText": "",
      "credit": "Pinterest (3); Collage: Condé Nast",
      "caption": ""
    }
  ],
  "categories": {
    "sections": [
      {
        "type": "category",
        "slug": "lifestyle",
        "name": "Lifestyle"
      }
    ]
  },
  "publishHistory": {
    "pubDate": "2017-06-08T15:20:00.000Z",
    "uri": "people-kultur/kultur-tipps/die-perfekte-feier-der-grosse-vogue-gartenparty-guide"
  }
}

This endpoint retrieves a specific article.

HTTP Request

GET /api/articles/{ID}

URL Path Parameters

Parameter Description
ID The ID of the article to retrieve

Response

Status Code: 200

Content Type: application/json

Resource model: Article

Get Native Article

curl "http://flyway-api-demo.example.com/api/nativearticles/2"

The above command returns JSON structured like this:

{
  "type": "nativearticle",
  "id": "0a14",
  "brand": "dmo",
  "lang": "de-DE",
  "hed": "Native article example",
  "body": "**Native article body copy supports exactly the same styles and embeds as the regular Article model.**\n\nVeggies es bonus vobis, proinde vos postulo essum magis kohlrabi welsh onion daikon amaranth tatsoi tomatillo melon azuki bean garlic.\n\nGumbo beet greens corn soko endive gumbo gourd. _Parsley_ shallot courgette tatsoi pea sprouts fava bean collard greens dandelion okra wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.\n\n## Heading 2\n\nTurnip greens yarrow ~~ricebean~~ rutabaga endive [cauliflower](http://www.foo.com) sea lettuce kohlrabi amaranth water spinach avocado daikon napa cabbage asparagus winter purslane kale. Celery potato scallion desert raisin horseradish spinach carrot soko. Lotus root water spinach fennel kombu maize bamboo shoot green bean swiss chard seakale pumpkin onion chickpea gram corn pea. Brussels sprout coriander water chestnut gourd swiss chard wakame kohlrabi beetroot carrot watercress. \n\n### Heading 3\n\nCorn amaranth salsify bunya nuts nori azuki bean chickweed potato bell pepper artichoke.\n\n[#image: /photos/710f]|||Image caption|||\n\nNori grape silver beet broccoli kombu beet greens fava bean potato quandong celery. Bunya nuts black-eyed pea prairie turnip leek lentil turnip greens parsnip. Sea lettuce lettuce water chestnut eggplant winter purslane fennel azuki bean earthnut pea sierra leone bologi leek soko chicory celtuce parsley jícama salsify.\n\n[#video: https://www.youtube.com/embed/ZCTBHm29SrM]\n\nCelery quandong swiss chard chicory earthnut pea potato. Salsify taro catsear garlic gram celery bitterleaf wattle seed collard greens nori. Grape wattle seed kombu beetroot horseradish carrot squash brussels sprout chard.\n\n#### Heading 4\n\n> Celery quandong swiss chard chicory earthnut pea potato. Salsify taro catsear garlic gram celery bitterleaf wattle seed collard greens nori. \n\nGrape wattle seed kombu beetroot horseradish carrot squash brussels sprout chard.",
  "dek": "This is an example of a native article for the Migrations team",
  "bylineOption": "produced",
  "campaignUrl": "http://www.foo.com",
  "seoCategory": "evergreen",
  "seoTitle": "SEO title example",
  "seoDescription": "SEO description example",
  "tags": [
    "migration",
    "article",
    "team"
  ],
  "contentSource": "vogue_international",
  "rubric": "Example kicker",
  "ledeCaption": "Here's the story [image](http://foo.com)",
  "canonicalUrl": "",
  "socialTitle": "Here's the test social title",
  "socialDescription": "Here's the test social description",
  "promoHed": "Here's the promo title",
  "self": "https://flyway-api-demo.example.com/api/nativearticles/0a14",
  "inline": [
    {
      "type": "photo",
      "id": "710f",
      "filename": "1.-GettyImages-645856368.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/710e_1.-GettyImages-645856368.jpg",
      "title": "94704490",
      "credit": "Jason LaVeris",
      "cropMode": "TOP",
      "restrictCropping": false
    }
  ],
  "advertiser": [
    {
      "type": "advertiser",
      "id": "1151",
      "name": "Prada",
      "url": "http://prada.com",
      "photosLogo": [
        {
          "type": "photo",
          "id": "c1df",
          "filename": "ipad_logo_nero.png",
          "url": "http://www.prada.com/etc/designs/prada/images/base/ipad_logo_nero.png",
          "title": "ipad_logo_nero.png",
          "cropMode": "TOP",
          "credit": "Prada"
        }
      ]
    }
  ],
  "photosLede": [
    {
      "type": "photo",
      "id": "b1de",
      "filename": "todas_las_imagenes_del_desfile_de_victorias_secret_en_shanghai_946146708.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/b1dd_todas_las_imagenes_del_desfile_de_victorias_secret_en_shanghai_946146708.jpg",
      "title": "775074876KS00007_2017_Victo",
      "credit": "Frazer Harrison",
      "cropMode": "TOP",
      "restrictCropping": false
    }
  ],
  "photosSocial": [
    {
      "type": "photo",
      "id": "b1de",
      "filename": "todas_las_imagenes_del_desfile_de_victorias_secret_en_shanghai_946146708.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/b1dd_todas_las_imagenes_del_desfile_de_victorias_secret_en_shanghai_946146708.jpg",
      "title": "775074876KS00007_2017_Victo",
      "credit": "Frazer Harrison",
      "cropMode": "TOP",
      "restrictCropping": false
    }
  ],
  "photosTout": [
    {
      "type": "photo",
      "id": "b1de",
      "filename": "todas_las_imagenes_del_desfile_de_victorias_secret_en_shanghai_946146708.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/b1dd_todas_las_imagenes_del_desfile_de_victorias_secret_en_shanghai_946146708.jpg",
      "title": "775074876KS00007_2017_Victo",
      "credit": "Frazer Harrison",
      "cropMode": "TOP",
      "restrictCropping": false
    }
  ],
  "contributorsAuthor": [
    {
      "type": "contributor",
      "id": "6361",
      "name": "Silke Friedrich",
      "tags": [],
      "uri": "die-redaktion/silke-friedrich"
    }
  ],
  "categories": {
    "sections": [
      {
        "type": "category",
        "slug": "beauty",
        "name": "Beauty"
      }
    ]
  },
  "publishHistory": {
    "pubDate": "2018-02-22T12:34:53.459Z",
    "uri": "beauty/anzeige/native-article-example"
  }
}

This endpoint retrieves a specific native article. It may be exposed on the same endpoint as a standard article if id is unique across all content types.

HTTP Request

GET /api/nativearticles/{ID}

Or if native articles are returned from the same endpoint as standard articles

GET /api/articles/{ID}

URL Path Parameters

Parameter Description
ID The ID of the native article to retrieve

Response

Status Code: 200

Content Type: application/json

Resource model: Native Article

Get All Galleries

curl "http://flyway-api-demo.example.com/api/galleries"

The above command returns JSON structured like this:

{
  "page": 1,
  "totalCount": 12,
  "brand": "dmo",
  "self": "http://flyway-api-demo.example.com/api/galleries",
  "next":  "http://flyway-api-demo.example.com/api/galleries?page=2",
  "hasMore": true,
  "data": [
    {
      "hed": "Hi, I'm an gallery on page 1 of a paginated list",
      "id": 1,
      "self": "http://flyway-api-demo.example.com/api/galleries/1",
      "type": "gallery"
    },
    {
      "hed": "Hi, I'm an gallery on page 1 of a paginated list",
      "id": 2,
      "self": "http://flyway-api-demo.example.com/api/galleries/2",
      "type": "gallery"
    },
    // Snip,
    {
      "hed": "Hi, I'm an gallery on page 1 of a paginated list",
      "id": 9,
      "self": "http://flyway-api-demo.example.com/api/galleries/9",
      "type": "gallery"
    },
    {
      "hed": "Hi, I'm an gallery on page 1 of a paginated list",
      "id": 10,
      "self": "http://flyway-api-demo.example.com/api/galleries/10",
      "type": "gallery"
    }
  ]
}

This endpoint retrieves all galleries. The response follows the pagination scheme laid out above.

HTTP Request

GET /api/galleries

Query Parameters

See Get All Articles Query Parameters section.

Response

A paginated response containing items of type gallery.

All galleries in the response must include the following fields:

Field Description
id the gallery ID in the integration system
type always gallery
self a link which must contain the URL to retrieve the fully hydrated gallery

Other fields from the full gallery response may be included. These will not be used by Flyway but can help with diagnostics and human readability.

curl "http://flyway-api-demo.example.com/api/galleries/2"

The above command returns JSON structured like this:

{
  "type": "gallery",
  "id": "6dfd",
  "brand": "dmo",
  "lang": "de-DE",
  "hed": "Der große VOGUE-Gartenparty-Guide",
  "dek": "Tanzen unter Sternenhimmel, Sommerklänge und Soulfood: Es ist die Ungezwungenheit, die das Feiern im Freien so besonders macht. So gelingt die perfekte Gartenparty mit ein paar Handgriffen und DIY-Ideen garantiert. Worauf warten Sie noch? Auf drei geht's los! \r\n",
  "seoTitle": "Der große VOGUE-Gartenparty-Guide",
  "seoDescription": "So gelingt die perfekte Gartenparty mit ein paar Handgriffen und DIY-Ideen! Worauf warten Sie noch? Auf drei geht's los! \r\n",
  "tags": [
    "Party-Looks",
    "Partys",
    "Sommertrends"
  ],
  "rubric": "Die perfekte Feier ",
  "socialTitle": "Der große VOGUE-Gartenparty-Guide",
  "socialDescription": "So gelingt die perfekte Gartenparty ",
  "promoHed": "Der große VOGUE-Gartenparty-Guide",
  "photosSocial": [
    {
      "type": "photo",
      "id": "b1de",
      "filename": "todas_las_imagenes_del_desfile_de_victorias_secret_en_shanghai_946146708.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/b1dd_todas_las_imagenes_del_desfile_de_victorias_secret_en_shanghai_946146708.jpg",
      "title": "775074876KS00007_2017_Victo",
      "credit": "Frazer Harrison",
      "cropMode": "TOP",
      "restrictCropping": false
    }
  ],
  "photosTout": [
    {
      "type": "photo",
      "id": "34c6",
      "credit": "Pinterest (3); Collage: Condé Nast",
      "filename": "gartenparty-tischdekoration-blumen.jpg",
      "url": "https://flyway-api-demo.example.com/public/images/34c5_gartenparty-tischdekoration-blumen.jpg",
      "tags": [],
      "caption": "",
      "title": "gartenparty-tischdekoration-blumen.jpg"
    }
  ],
  "self": "https://flyway-api-demo.example.com/api/galleries/6dfd",
  "contributorsAuthor": [
    {
      "type": "contributor",
      "id": "c3c7",
      "name": "Jana Ackermann",
      "tags": [],
      "uri": "die-redaktion/jana-ackermann"
    }
  ],
  "items": [
    {
      "caption": "This food was really horrible within the context of this gallery!",
      "photo": {
        "type": "photo",
        "id": "586d",
        "altText": "some alt text",
        "caption": "the global caption for this photo that this gallery overrides",
        "title": "some-food.jpg",
        "tags": [],
        "filename": "some-food.jpg",
        "url": "https://flyway-api-demo.example.com/public/images/586d_some-food.jpg",
        "credit": "Pinterest"
      }
    },
    {
      "caption": "This food was really delicious within the context of this gallery!",
      "photo": {
        "type": "photo",
        "id": "544a",
        "altText": "some more alt text",
        "caption": "another global caption for this photo that this gallery overrides",
        "title": "some-more-food.jpg",
        "tags": [],
        "filename": "some-more-food.jpg",
        "url": "https://flyway-api-demo.example.com/public/images/544a_some-more-food.jpg",
        "credit": "Pinterest"
      }
    },
    {
      "caption": "This food was really questionable within the context of this gallery.",
      "photo": {
        "type": "photo",
        "id": "586d",
        "altText": "some alt text",
        "caption": "the global caption for this photo that this gallery overrides",
        "title": "some-tasty-foo.jpg",
        "tags": [],
        "filename": "some-tasty-foo.jpg",
        "url": "https://flyway-api-demo.example.com/public/images/586d_some-tasty-foo.jpg",
        "credit": "Pinterest"
      }
    }
  ],
  "categories": {
    "sections": [
      {
        "type": "category",
        "slug": "lifestyle",
        "name": "Lifestyle"
      }
    ]
  },
  "publishHistory": {
    "pubDate": "2017-06-08T15:20:00.000Z",
    "uri": "people-kultur/kultur-tipps/die-perfekte-feier-der-grosse-vogue-gartenparty-guide"
  }
}

This endpoint retrieves a specific gallery.

HTTP Request

GET /api/galleries/{ID}

URL Path Parameters

Parameter Description
ID The ID of the gallery to retrieve

Response

Status Code: 200

Content Type: application/json

Resource model: Gallery

Fashion Show Reviews Integration API Guidelines

This document contains guidelines for implementing an integration API for migrating Fashion Show reviews from a market CMS and transforming that data into a format that provides all of the information needed for Flyway to create and associate the review to the correct fashion show.

All responses to the following requests should be returned in valid JSON to be parsed by Flyway.

If any further assistance is needed, please feel free to contact the CNI Vogue Runway team at runway.product@condenastint.com

Step-by-step guide

In order to migrate a batch of reviews in Flyway, an integration API that returns a list of entities to be migrated (in this case reviews) needs to be created.

The batch endpoint needs to provide an object with the following key value pairs for flyway to consume correctly:

"https://fashion-shows-flyway.staging.cni.digital/reviews"

The above command for reviews returns JSON structured like this:

{
  "page": 1,
  "totalCount": 20926,
  "next": "https://fashion-shows-flyway.staging.cni.digital/reviews?page=2",
  "hasMore": true,
  "brand": "fashionshows",
  "self": "https://fashion-shows-flyway.staging.cni.digital/reviews",
  "data": [
    {
    "id": "5cfdcdc3080a3f1b6cd962f8",
    "type": "review",
    "self": "https://fashion-shows-flyway.staging.cni.digital/reviews/5cfdcdc3080a3f1b6cd962f8"
    },
    {
    "id": "5cfda826ef56f848109a3236",
    "type": "review",
    "self": "https://fashion-shows-flyway.staging.cni.digital/reviews/5cfda826ef56f848109a3236"
    },
    {
    "id": "5cfd93336dabb4834e1a4dad",
    "type": "review",
    "self": "https://fashion-shows-flyway.staging.cni.digital/reviews/5cfd93336dabb4834e1a4dad"
    },
    {
    "id": "5cfd884de8d14c2f34aae865",
    "type": "review",
    "self": "https://fashion-shows-flyway.staging.cni.digital/reviews/5cfd884de8d14c2f34aae865"
    },
    {
    "id": "5cfd7b094593fd01de139162",
    "type": "review",
    "self": "https://fashion-shows-flyway.staging.cni.digital/reviews/5cfd7b094593fd01de139162"
    },
    {
    "id": "5cfd4b16ef56f814d79a31f8",
    "type": "review",
    "self": "https://fashion-shows-flyway.staging.cni.digital/reviews/5cfd4b16ef56f814d79a31f8"
    },
    {
    "id": "5cfd6cb7ef56f8ec9c9a321b",
    "type": "review",
    "self": "https://fashion-shows-flyway.staging.cni.digital/reviews/5cfd6cb7ef56f8ec9c9a321b"
    },
    {
    "id": "5cfd5817adfd096cd8246aa3",
    "type": "review",
    "self": "https://fashion-shows-flyway.staging.cni.digital/reviews/5cfd5817adfd096cd8246aa3"
    },
    {
    "id": "5cfd3cb5e8d14cf439aae81c",
    "type": "review",
    "self": "https://fashion-shows-flyway.staging.cni.digital/reviews/5cfd3cb5e8d14cf439aae81c"
    },
  ]
}
Key Type Required Value Description Example Value
page integer no (yes if more than 1 page exists) For if the endpoint is paginated due to the total number of entities to migrate. 1
totalCount integer yes Representing the total number of review entities to migrate (sum across all pages) 19065
next string no The url for the next paginated set of reviews to migrate "https://fashion-shows-flyway.staging.cni.digital/reviews?page=3"
hasMore boolean yes Flag indicating if there is a further page of entities to migrate beyond the current true
brand string yes This should contain the string "fashionshows"; indicates the content API that flyway should be migrating to. "fashionshows"
self string yes A link to the base url for batch migrations "https://fashion-shows-flyway.staging.cni.digital/reviews"
data array yes An array containing objects representing the review entities to migrate, containing the following key: values:
1. id - a unique identifier for this review (used as a reference to your original data source/CMS)
2. type - this should contain "review"; indicates the entity type within the fashionshows content API to migrate to self
3. the url to the individual entity in its integration API transformed format, to be migrated
[{
"id": "55c685dfc4e6a2d8dced238a",
"type": "review",
"self": "https://fashion-shows-flyway.staging.cni.digital/reviews/55c685dfc4e6a2d8dced238a"
},
{
"id": "55c6858fc4e6a2d8dced0a7c",
"type": "review",
"self": "https://fashion-shows-flyway.staging.cni.digital/reviews/55c6858fc4e6a2d8dced0a7c"
}]

Individual Review Entities

Each individual review entity should be obtainable via a GET to each URL provided within the data array, and should/can provide the following fields of data:

"https://fashion-shows-flyway.staging.cni.digital/reviews/5c7ed8145f91f02d6b73aee3"

The above command for a review entity returns JSON structured like this:

{
  "id": "5c7ed8145f91f02d6b73aee3",
  "body": "In a season marked by rising young upstarts, here are two names to bookmark, lest you be late to the next party: Dami Kwon and Jessica Jung, cofounders of the Seoul-based concept shop Rare Market and its three-year-old label, We11done. What could have been another in-house line of basics has become the go-to source for those hoping to catch a whiff of the Korean cool that’s so on trend. Kwon and Jung have knowingly tapped into that somewhat fetishistic yen, but they’ve delivered great clothes for young working women, not defined by any one place. \n\n“We would like to define a new luxury for ourselves,” said Jung—ourselves being the key word, as their work is grounded by the deeply personal elements in their wardrobes. This season, that meant tailoring of the manner that defined ’90s icons like Tom Ford and Helmut Lang. We11done does not suffer delusions of that grandeur, of course; they’re not here to reinvent the wheel. Instead, Kwon and Jung are engaged in the exercise of creating clothes for real women, of sorting through their past, present, and future to make something of the moment. \n\nTake the sky blue collared shirt, which was cut from such a thick bonded satin that it held its sculptural contours. That satin also worked wonderfully well on a sharp blazer in a classic deep aubergine color, closed by a single button to reveal a sliver of stomach. Despite the homage to classic high-end luxury, every leather item—from the white patent snakeskin pant to the camel-hued stretch turtleneck to the boxy black pullover with snake-stamped pockets—is vegan and all the fur is faux. \n\nIt’s smart, given the way tides have turned. But a keen eye for trends has always been their greatest strength. You can see it in details like a scrunched keyhole back on a leather top, the clever use of chenille on a scoop neck, those rich satin shirts, and the neat rectangular bags, designed to fit snugly under one arm. Kwon and Jung are here to prove that good taste is not just a Western thing. There are young women all over the world who want to dress just like them. ",
  "marketBrand": "us",
  "pubDate": "2019-03-05T20:12:30.784Z",
  "brandCode": "we11done",
  "seasonCode": "fall-2019-ready-to-wear",
  "status": "published",
  "archived": false,
  "rels": {
    "author": [
      {
        "id": "560c4d3fe72b1b1e7a097546",
        "name": "Monica Kim",
        "email": "",
        "socialMedia": [
          {
          "network": "Twitter",
          "handle": "monicamkim"
          },
          {
          "network": "Instagram",
          "handle": "monmoon"
          },
          {
          "network": "Vogue.com",
          "handle": "/contributor/monica-kim"
          }
        ],
        "bio": "Vogue’s Senior Fashion News Editor likes cats, Khaleesi, and K-pop.",
        "marketBrand": "us",
        "pubDate": "2017-01-12T01:43:59.000Z",
        "status": "published",
        "rels": {
          "photosTout": [
            {
            "id": "58584b5744b5d45318dc9566",
            "title": "monica-kim-pic.jpg",
            "caption": "",
            "restrictCropping": false,
            "credit": "",
            "filename": "monica-kim-pic.jpg",
            "notes": "13362051",
            "url": "https://stg-vulcan-api.aws.conde.io/vogue-services/photos/58584b5744b5d45318dc9566/master/c_limit/58584b5744b5d45318dc9565_monica-kim-pic.jpg",
            "type": "photo",
            "archived": false
            }
          ]
        },
        "type": "contributor"
      }
    ]
  },
  "type": "review"
}
Key Type Required Value Description Example Value
id string yes A unique identifier for this review (should match the URL) - a back reference to the source CMS "5c7ed8145f91f02d6b73aee3"
body string yes The raw markdown (rich text formatted) content of the review. (can be empty string) "This is an example review of a fashion show."
marketBrand string yes The market to save this review to - must be one of the following:
'us', 'de', 'es', 'fr', 'it', 'mx', 'uk', 'in', 'ru', 'cn', 'jp', 'tw'
"us"
pubDate string(ISO date format) no The publish date of the review if it should be migrated as a live in production review. ISO formatted date converted to a string. "2019-03-11T16:48:08.894Z"
brandCode string yes The name of the brand from the fashionshow that this review is associated with, converted into all lower case characters, accented characters removed, and spaces replaced with - "tommy-hilfiger"
seasonCode string yes The name of the season of the fashionshow that this review is associated with, converted into all lower case characters, accented characters removed, and spaces replaced with -. To determine the format of the season code please see the diagram below "fall-2019-ready-to-wear"
status string yes The editorial state of the review; must be one of: draft, published or expired. "published"
archived boolean yes If the review has been deleted/archived, the review can be stored for archival purposes by setting this flag to true, otherwise in most cases this should be false false
rels object no Contains any related objects, typically the only one to concern for a review is the author, which is a rel of type contributor {"author": [
see below
]}
type string yes The type of entity, this should be review "review"

Season code format:

season code format diagram

Review Author Entities

The rels object in the review can contain an author object of type contributor to relate the review to:

"https://fashion-shows-flyway.staging.cni.digital/contributors/560c4d3fe72b1b1e7a097546"

The above command for a contributor returns JSON structured like this:

{
  "id": "560c4d3fe72b1b1e7a097546",
  "name": "Monica Kim",
  "email": "",
  "socialMedia": [
    {
    "network": "Twitter",
    "handle": "monicamkim"
    },
    {
    "network": "Instagram",
    "handle": "monmoon"
    },
    {
    "network": "Vogue.com",
    "handle": "/contributor/monica-kim"
    }
  ],
  "bio": "Vogue’s Senior Fashion News Editor likes cats, Khaleesi, and K-pop.",
  "marketBrand": "us",
  "pubDate": "2017-01-12T01:43:59.000Z",
  "status": "published",
  "rels": {
    "photosTout": [
      {
      "id": "58584b5744b5d45318dc9566",
      "title": "monica-kim-pic.jpg",
      "caption": "",
      "restrictCropping": false,
      "credit": "",
      "filename": "monica-kim-pic.jpg",
      "notes": "13362051",
      "url": "https://stg-vulcan-api.aws.conde.io/vogue-services/photos/58584b5744b5d45318dc9566/master/c_limit/58584b5744b5d45318dc9565_monica-kim-pic.jpg",
      "type": "photo",
      "archived": false
      }
    ]
  },
  "type": "contributor"
}
Key Type Required Value Description Example Value
id string yes A unique identifier for this review (should match the URL) - a back reference to the source CMS "560c4d3fe72b1b1e7a097546"
name string yes The full name of the contributor "Anna Wintour"
email string no The email of the contributor "aw@cni.com"
socialMedia array no An array containing objects with any social media account info, each object containing:
network - the social media network the handle is for
handle - the user identity on this network
[
{
"network": "Twitter",
"handle": "monicamkim"
},
{
"network": "Instagram",
"handle": "monmoon"
},
{
"network": "Vogue.com",
"handle": "/contributor/monica-kim"
}
]
bio string no An optional description that gives a summary of who the contributor is. "A short, personal description of the author."
marketBrand string yes The market to save this contributor to - must be one of the following:
'us', 'de', 'es', 'fr', 'it', 'mx', 'uk', 'in', 'ru', 'cn', 'jp', 'tw'
"us"
pubDate string(ISO date format) no The publish date of the contributor if it should be migrated as a live in production contributor. ISO formatted date converted to a string. "2019-03-11T16:48:08.894Z"
status string yes The editorial state of the contributor; must be one of: draft, published or expired. "published"
rels object no Contains any related objects, typically the only one to concern for a contributor are a photosTout to be displayed on their bio, which is a rel of type photo {"photosTout": [
see below
]}
type string yes The type of entity, this should be contributor "contributor"

Author Photos

If the contributor has a photo to associate with their profile, it can be provided as a photosTout rel in the contributor entity.

"https://fashion-shows-flyway.staging.cni.digital/photos/58584b5744b5d45318dc9566"

The above command for a photo returns JSON structured like this:

{
  "id": "58584b5744b5d45318dc9566",
  "title": "monica-kim-pic.jpg",
  "caption": "",
  "restrictCropping": false,
  "credit": "",
  "filename": "monica-kim-pic.jpg",
  "notes": "13362051",
  "url": "https://stg-vulcan-api.aws.conde.io/vogue-services/photos/58584b5744b5d45318dc9566/master/c_limit/58584b5744b5d45318dc9565_monica-kim-pic.jpg",
  "type": "photo",
  "archived": false
}
Key Type Required Value Description Example Value
id string yes A unique identifier for this review (should match the URL) - a back reference to the source CMS "560c4d3fe72b1b1e7a097546"
title string yes This should match the filename (including the extension) "filename-123.jpg"
caption string no A short description of the photo "caption"
restrictCropping boolean no Defaults to false. false
credit string no Credit for the photo provider. "PR"
filename string yes The name of the file (including extension). "filename-123.jpg"
notes string no "13343875"
url string yes Full URL to the source photo file to be migrated. "https://stg-vulcan-api.aws.conde.io/vogue-services/photos/58584b5744b5d45318dc9566/master/c_limit/filename-123.jpg"
type string yes The type of entity, this should be photo "photo"
archived boolean no If the photo has been deleted but needs to be stored for archival purposes, this can be set to true, otherwise typically false. false

Errors

The Flyway Integration API uses the following error codes:

Error Code Meaning
400 Bad Request -- Your request is likely malformed.
401 Unauthorized -- Your authentication credentials are invalid.
403 Forbidden -- You don't have the necessary permissions to access this content.
404 Not Found -- The specified resource could not be found.
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.